4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 1997-2002 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
31 * Manages mapping between a security principal name and unix uid
39 #include <gssapi/gssapi_ext.h>
42 #define MAX_STR_LEN 1024
48 static void usage(void);
49 static void addUser(const char *name
, const char *oid
, const char *userUid
,
50 const char *userComment
, const char *userMech
);
51 static int file_listUsers(const gss_OID mechOid
, const char *userUid
,
53 static int listUsers(const char *name
, const char *nameTypeOid
,
54 const char *uid
, const char *mechOid
);
55 static int file_removeUsers(const gss_OID mechOid
, const char *userUid
,
57 static int removeUsers(const char *name
, const char *nameTypeOid
,
58 const char *uid
, const char *mechOid
);
63 static int tableSource
;
64 static char *PROG_NAME
= NULL
;
67 main(int argc
, char *args
[])
69 char *userName
= NULL
, *nameTypeOID
= NULL
,
70 *uid
= NULL
, *comment
= NULL
, *mech
= NULL
,
77 /* set locale and domain for internationalization */
78 setlocale(LC_ALL
, "");
79 textdomain(TEXT_DOMAIN
);
84 /* Process the input arguments */
85 while ((c
= getopt(argc
, args
, "arln:o:u:m:c:")) != EOF
) {
122 /* determine which back-end to use as the gsscred store */
123 tableSource
= gsscred_read_config_file();
125 /* perform the requested operation */
128 addUser(userName
, nameTypeOID
, uid
, comment
, mech
);
132 removeUsers(userName
, nameTypeOID
, uid
, mech
);
136 listUsers(userName
, nameTypeOID
, uid
, mech
);
142 fprintf(stdout
, "\n");
147 * Handles the addition of users to the gsscred table.
150 addUser(const char *name
, const char *nameOidStr
,
151 const char *userUid
, const char *userComment
,
152 const char *mechOidStr
)
155 gss_buffer_desc fullName
= GSS_C_EMPTY_BUFFER
,
156 hexBufDesc
= GSS_C_EMPTY_BUFFER
,
157 hexMechOid
= GSS_C_EMPTY_BUFFER
;
158 char comment
[MAX_STR_LEN
+1], hexBuf
[MAX_STR_LEN
+MAX_STR_LEN
+1],
159 hexMechOidBuf
[MAX_STR_LEN
+1], *commentPtr
= NULL
,
160 *errDetail
= NULL
, uidStr
[256], *uidPtr
;
161 struct passwd
*aUser
;
163 int count
= 0, retCode
;
165 hexMechOid
.length
= MAX_STR_LEN
;
166 hexMechOid
.value
= (void*)hexMechOidBuf
;
168 /* addition of users can only be performed by super users */
171 gettext("\nUser addition requires"
172 " root privileges."));
176 /* the mechanism OID is required */
177 if (mechOidStr
== NULL
) {
178 fprintf(stderr
, gettext("\nUnspecified mechanism."));
182 /* Convert from string mechanism Oid to ASN.1 oid and then hex */
183 if (__gss_mech_to_oid(mechOidStr
, &mechOid
) != GSS_S_COMPLETE
) {
185 gettext("\nInvalid mechanism specified [%s]."),
190 hexBufDesc
.length
= mechOid
->length
;
191 hexBufDesc
.value
= mechOid
->elements
;
193 if (!gsscred_AsHex(&hexBufDesc
, &hexMechOid
)) {
195 gettext("\nInternal error. "
196 "Conversion to hex failed."));
201 * if the name is specified, then do single addition.
202 * Might have to look up the uid.
205 hexBufDesc
.length
= sizeof (hexBuf
);
206 hexBufDesc
.value
= hexBuf
;
208 /* build the name as needed */
209 if (!gsscred_MakeName(mechOid
, name
, nameOidStr
, &fullName
)) {
211 gettext("\nError adding user [%s]."), name
);
215 /* convert it to hex */
216 if (!gsscred_AsHex(&fullName
, &hexBufDesc
)) {
217 gss_release_buffer(&minor
, &fullName
);
219 gettext("\nInternal error. "
220 "Conversion to hex failed."));
224 /* might require the lookup of the uid if one not specified */
225 if (userUid
== NULL
) {
227 if ((aUser
= getpwnam(name
)) == NULL
) {
229 gettext("\nUnable to obtain password"
230 " information for [%s]."),
232 gss_release_buffer(&minor
, &fullName
);
235 sprintf(uidStr
, "%ld", aUser
->pw_uid
);
239 uidPtr
= (char *)userUid
;
241 if (userComment
== NULL
) {
242 sprintf(comment
, "%s, %s", name
, mechOidStr
);
243 commentPtr
= comment
;
245 commentPtr
= (char *)userComment
;
247 if (tableSource
== GSSCRED_FLAT_FILE
)
248 retCode
= file_addGssCredEntry(&hexBufDesc
,
249 uidPtr
, commentPtr
, &errDetail
);
251 /* other backends (ldap, dss) coming soon */
255 fprintf(stderr
, gettext("\nError adding user [%s]."),
259 fprintf(stderr
, "\n%s\n", errDetail
);
265 gss_release_buffer(&minor
, &fullName
);
270 * since no name specified, then we will load everyone from
271 * password table. This means that -u and -o options are invalid.
272 * We just ignore it, but we could flag it as error.
276 while ((aUser
= getpwent()) != NULL
) {
277 hexBufDesc
.length
= sizeof (hexBuf
);
278 hexBufDesc
.value
= hexBuf
;
280 if (!gsscred_MakeName(mechOid
, aUser
->pw_name
,
281 nameOidStr
, &fullName
)) {
283 gettext("\nError adding user [%s]."),
288 if (!gsscred_AsHex(&fullName
, &hexBufDesc
)) {
289 gss_release_buffer(&minor
, &fullName
);
291 gettext("\nInternal error. "
292 "Conversion to hex failed."));
296 sprintf(uidStr
, "%ld", aUser
->pw_uid
);
297 sprintf(comment
, "%s, %s", aUser
->pw_name
, mechOidStr
);
298 if (tableSource
== GSSCRED_FLAT_FILE
)
299 retCode
= file_addGssCredEntry(&hexBufDesc
,
300 uidStr
, comment
, &errDetail
);
306 gettext("\nError adding user [%s]."),
310 fprintf(stderr
, "\n%s\n", errDetail
);
316 if ((count
% 50) == 0)
318 gettext("\n[%d] users added..."),
321 gss_release_buffer(&minor
, &fullName
);
328 * Handles the searching of the gsscred table.
330 static int listUsers(const char *name
, const char *nameOidStr
,
331 const char *uidStr
, const char *mechOidStr
)
333 GssCredEntry
*entryPtr
, *entryTmpPtr
;
335 hexName
[(MAX_STR_LEN
*2) + 1];
336 gss_OID anOid
= NULL
, userMechOid
= NULL
;
337 gss_OID_set mechSet
= NULL
;
338 gss_buffer_desc inBufDesc
= GSS_C_EMPTY_BUFFER
,
339 outBufDesc
= GSS_C_EMPTY_BUFFER
,
340 searchName
= GSS_C_EMPTY_BUFFER
;
341 int status
= 1, numOfMechs
, i
;
343 char *errDetails
= NULL
;
345 /* Do we need to convert the mechanism oid? */
346 if (mechOidStr
!= NULL
) {
348 if (__gss_mech_to_oid(mechOidStr
, &userMechOid
) !=
351 gettext("\nInvalid mechanism specified [%s]."),
355 inBufDesc
.length
= userMechOid
->length
;
356 inBufDesc
.value
= userMechOid
->elements
;
357 outBufDesc
.length
= sizeof (hexMech
);
358 outBufDesc
.value
= hexMech
;
360 if (!gsscred_AsHex(&inBufDesc
, &outBufDesc
)) {
362 gettext("\nInternal error. "
363 "Conversion to hex failed."));
368 } /* mechOidStr != NULL */
370 /* are we retrieving everyone ? or searching by mech ? */
371 if ((name
== NULL
&& uidStr
== NULL
&& mechOidStr
== NULL
) ||
372 (name
== NULL
&& uidStr
== NULL
)) {
374 if (tableSource
== GSSCRED_FLAT_FILE
) {
375 file_listUsers(userMechOid
, NULL
, &errDetails
);
379 gettext("\nError searching gsscred"
391 /* Are we searching by uid or uid and mech? */
392 if (name
== NULL
&& uidStr
!= NULL
) {
394 if (tableSource
== GSSCRED_FLAT_FILE
)
395 file_listUsers(userMechOid
, uidStr
, &errDetails
);
398 while (entryPtr
!= NULL
) {
399 fprintf(stdout
, "\n%s\t%d\t%s",
400 entryPtr
->principal_name
,
401 entryPtr
->unix_uid
, entryPtr
->comment
);
402 free(entryPtr
->principal_name
);
403 free(entryPtr
->comment
);
404 entryTmpPtr
= entryPtr
->next
;
406 entryPtr
= entryTmpPtr
;
410 /* check for any errors */
413 gettext("\nError searching gsscred table "
425 * We are searching by name;
426 * how many mechs must we check?
428 if (mechOidStr
== NULL
) {
430 if (gss_indicate_mechs(&minor
, &mechSet
) != GSS_S_COMPLETE
) {
432 gettext("\nInternal error. "
433 "GSS-API call failed."));
436 numOfMechs
= mechSet
->count
;
441 /* now look through all the mechs searching */
442 for (i
= 0; i
< numOfMechs
; i
++) {
444 if (mechOidStr
== NULL
) {
445 anOid
= &mechSet
->elements
[i
];
446 inBufDesc
.length
= anOid
->length
;
447 inBufDesc
.value
= anOid
->elements
;
448 outBufDesc
.length
= sizeof (hexMech
);
449 outBufDesc
.value
= hexMech
;
451 if (!gsscred_AsHex(&inBufDesc
, &outBufDesc
))
456 /* create a gss name */
457 if (!gsscred_MakeName(anOid
, name
, nameOidStr
, &outBufDesc
))
460 /* now convert it to hex, and find it */
461 searchName
.value
= hexName
;
462 searchName
.length
= sizeof (hexName
);
463 status
= gsscred_AsHex(&outBufDesc
, &searchName
);
464 free(outBufDesc
.value
);
469 if (tableSource
== GSSCRED_FLAT_FILE
)
470 file_getGssCredEntry(&searchName
, uidStr
, &errDetails
);
472 entryPtr
= NULL
; /* other backends coming soon */
473 while (entryPtr
!= NULL
) {
474 fprintf(stdout
, "\n%s\t%d\t%s",
475 entryPtr
->principal_name
,
476 entryPtr
->unix_uid
, entryPtr
->comment
);
477 free(entryPtr
->principal_name
);
478 free(entryPtr
->comment
);
479 entryTmpPtr
= entryPtr
->next
;
481 entryPtr
= entryTmpPtr
;
485 /* any errors to display */
488 gettext("\nError searching gsscred table "
499 gss_release_oid_set(&minor
, &mechSet
);
505 * Performs additional handling while searching for users
506 * stored in the flat file table.
509 file_listUsers(const gss_OID mechOid
, const char *unixUid
,
512 gss_buffer_desc mechBufDesc
= GSS_C_EMPTY_BUFFER
,
513 mechHexBufDesc
= GSS_C_EMPTY_BUFFER
;
514 char mechBuf
[128], mechHexBuf
[256];
516 if (mechOid
!= NULL
) {
517 /* must make the name header whic contains mech oid */
518 mechBufDesc
.value
= (void *) mechBuf
;
519 mechBufDesc
.length
= sizeof (mechBuf
);
520 mechHexBufDesc
.value
= (void*) mechHexBuf
;
521 mechHexBufDesc
.length
= sizeof (mechHexBuf
);
523 if ((!gsscred_MakeNameHeader(mechOid
, &mechBufDesc
)) ||
524 (!gsscred_AsHex(&mechBufDesc
, &mechHexBufDesc
))) {
525 (*errDetails
) = strdup(
526 gettext("\nInternal error. "
527 " Conversion to hex failed."));
531 return (file_getGssCredEntry(&mechHexBufDesc
,
532 unixUid
, errDetails
));
535 return (file_getGssCredEntry(NULL
, unixUid
, errDetails
));
536 } /* file_listUsers */
540 * Handles the deletion of users.
542 static int removeUsers(const char *name
, const char *nameOidStr
,
543 const char *uidStr
, const char *mechOidStr
)
546 hexName
[(MAX_STR_LEN
*2) + 1],
548 gss_OID anOid
= NULL
, userMechOid
= NULL
;
549 gss_OID_set mechSet
= NULL
;
550 gss_buffer_desc inBufDesc
= GSS_C_EMPTY_BUFFER
,
551 outBufDesc
= GSS_C_EMPTY_BUFFER
,
552 searchName
= GSS_C_EMPTY_BUFFER
;
553 int status
= 0, numOfMechs
, i
;
557 /* user deletion can only be performed by super user */
561 gettext("\nUser deletion requires"
562 " root privileges."));
566 /* do we need to convert the mechanism oid? */
567 if (mechOidStr
!= NULL
) {
568 if (__gss_mech_to_oid(mechOidStr
, &userMechOid
) !=
571 gettext("\nInvalid mechanism specified [%s]."),
576 inBufDesc
.length
= userMechOid
->length
;
577 inBufDesc
.value
= userMechOid
->elements
;
578 outBufDesc
.length
= sizeof (hexMech
);
579 outBufDesc
.value
= hexMech
;
581 if (!gsscred_AsHex(&inBufDesc
, &outBufDesc
)) {
583 gettext("\nInternal error."
584 " Conversion to hex failed."));
589 } /* mechOidStr != NULL */
591 /* are we deleting the entire table or an entire mech ? */
592 if (name
== NULL
&& uidStr
== NULL
) {
594 if (tableSource
== GSSCRED_FLAT_FILE
)
595 status
= file_removeUsers(userMechOid
,
600 /* display any errors */
603 gettext("\nError deleting gsscred entry "
612 /* are we deleting by uid or uid and mech? */
613 if (name
== NULL
&& uidStr
!= NULL
) {
615 if (tableSource
== GSSCRED_FLAT_FILE
)
616 status
= file_removeUsers(userMechOid
, uidStr
,
621 /* check for any errors */
624 gettext("\nError deleting gsscred entry "
634 * We are deleting by name;
635 * how many mechs must we check?
637 if (mechOidStr
== NULL
) {
639 if (gss_indicate_mechs(&minor
, &mechSet
) != GSS_S_COMPLETE
) {
641 gettext("\nInternal error. "
642 "GSS-API call failed."));
646 numOfMechs
= mechSet
->count
;
651 /* now look through all the mechs, deleting */
652 for (i
= 0; i
< numOfMechs
; i
++) {
654 if (mechOidStr
== NULL
) {
655 anOid
= &mechSet
->elements
[i
];
656 inBufDesc
.length
= anOid
->length
;
657 inBufDesc
.value
= anOid
->elements
;
658 outBufDesc
.length
= sizeof (hexMech
);
659 outBufDesc
.value
= hexMech
;
660 if (!gsscred_AsHex(&inBufDesc
, &outBufDesc
))
665 /* create a gss name */
666 if (!gsscred_MakeName(anOid
, name
, nameOidStr
, &outBufDesc
))
669 /* now convert it to hex, and delete it */
670 searchName
.value
= hexName
;
671 searchName
.length
= sizeof (hexName
);
672 status
= gsscred_AsHex(&outBufDesc
, &searchName
);
673 free(outBufDesc
.value
);
678 if (tableSource
== GSSCRED_FLAT_FILE
)
679 status
= file_deleteGssCredEntry(&searchName
,
680 uidStr
, &errDetails
);
684 /* check for any errors */
687 gettext("\nError deleting gsscred entry"
697 gss_release_oid_set(&minor
, &mechSet
);
704 * Performs additional handling while deleting users
705 * stored in the flat file table.
707 int file_removeUsers(const gss_OID mechOid
, const char *unixUid
,
710 gss_buffer_desc mechBufDesc
= GSS_C_EMPTY_BUFFER
,
711 mechHexBufDesc
= GSS_C_EMPTY_BUFFER
;
712 char mechBuf
[128], mechHexBuf
[256];
714 if (mechOid
!= NULL
) {
716 * need to create the buffer header which contains
719 mechBufDesc
.value
= (void*) mechBuf
;
720 mechBufDesc
.length
= sizeof (mechBuf
);
721 mechHexBufDesc
.value
= (void *) mechHexBuf
;
722 mechHexBufDesc
.length
= sizeof (mechHexBuf
);
724 if ((!gsscred_MakeNameHeader(mechOid
, &mechBufDesc
)) ||
725 (!gsscred_AsHex(&mechBufDesc
, &mechHexBufDesc
))) {
726 (*errDetails
) = strdup(
727 gettext("\nInternal error."
728 " Conversion to hex failed."));
732 return (file_deleteGssCredEntry(&mechHexBufDesc
, unixUid
,
736 return (file_deleteGssCredEntry(NULL
, unixUid
, errDetails
));
737 } /* file_removeUsers */
741 * Prints the usage string, and terminates.
743 static void usage(void)
747 gettext("\nUsage:\t %s [-n user [-o oid] [-u uid]]"
748 " [-c comment] -m mech -a"
749 "\n\t %s [-n user [-o oid]] [-u uid] [-m mech] -r"
750 "\n\t %s [-n user [-o oid]] [-u uid] [-m mech] -l\n"),
751 PROG_NAME
, PROG_NAME
, PROG_NAME
);