2 * Copyright (c) 1991, 1992 Regents of the University of Michigan.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that this notice is preserved and that due credit is given
7 * to the University of Michigan at Ann Arbor. The name of the University
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided ``as is'' without express or implied warranty.
19 #include <sys/types.h>
21 #include <kerberosIV/krb.h>
24 #endif /* KERBEROS_V */
29 #include <ldapconfig.h>
32 extern LDAP *ld; /* our LDAP descriptor */
33 extern int verbose; /* verbosity indicator */
34 extern char *mygetpass(); /* getpass() passwds are too short */
37 extern int debug; /* debug flag */
41 static char tktpath[20]; /* ticket file path */
43 static int valid_tgt();
50 int rc; /* return code from ldap_bind() */
51 char *passwd = NULL; /* returned by mygetpass() */
52 char **rdns; /* for fiddling with the DN */
54 int name_provided; /* was a name passed in? */
55 struct passwd *pw; /* for getting user id */
58 char **krbnames; /* for kerberos names */
63 LDAPMessage *mp; /* returned from find() */
64 static char prompt[MED_BUF_SIZE]; /* place for us to sprintf the prompt */
65 static char name[MED_BUF_SIZE]; /* place to store the user's name */
66 static char password[MED_BUF_SIZE]; /* password entered by user */
67 extern struct entry Entry; /* look here for a name if needed */
68 extern LDAPMessage *find(); /* for looking up 'name' */
69 extern char *search_base; /* for printing later */
70 extern char *default_bind_object; /* bind as this on failure */
71 extern void printbase(); /* used to pretty-print a base */
72 extern int bind_status;
74 static void set_bound_dn();
78 fprintf(stderr, "auth(%s, NULL)\n", who);
80 name_provided = ( who != NULL );
83 * The user needs to bind. If <who> is not specified, we
84 * assume that authenticating as user id is what user wants.
86 if (who == NULL && implicit && (pw = getpwuid((uid_t)geteuid()))
87 != (struct passwd *) NULL) {
88 sprintf(uidname, "uid=%s", pw->pw_name);
89 /* who = pw->pw_name; /* */
95 printf( "You must first authenticate yourself to the Directory.\n" );
97 printf(" What is your name or uniqname? ");
99 printf(" What is your name or user id? ");
102 fetch_buffer(name, sizeof(name), stdin);
109 if (debug & D_AUTHENTICAT)
110 printf(" Authenticating as \"%s\"\n", who);
114 * Bail out if the name is bogus. If not, strip off the junk
115 * at the start of the DN, build a prompt, and get a password
116 * from the user. Then perform the ldap_bind().
118 if ((mp = find(who, TRUE)) == NULL) {
119 (void) ldap_msgfree(mp);
120 printf(" I could not find \"%s\" in the Directory.\n", who);
121 printf(" I used a search base of ");
122 printbase("", search_base);
125 if (debug & D_AUTHENTICAT)
126 printf(" Could not find \"%s\"\n", who);
132 * Fill in the Entry structure. May be handy later.
134 (void) parse_answer(mp);
136 rdns = ldap_explode_dn(Entry.DN, TRUE);
137 printf(" Authenticating to the directory as \"%s\"...\n", *rdns );
141 * First, if the user has a choice of auth methods, ask which
142 * one they want to use. if they want kerberos, ask which
143 * krbname they want to bind as.
146 if ( (krbnames = ldap_get_values( ld, mp, "krbName" )) != NULL ) {
147 int choice, hassimple;
149 hassimple = (ldap_compare_s( ld, Entry.DN,
150 "userPassword", "x" ) == LDAP_COMPARE_FALSE);
151 (void) ldap_msgfree(mp);
153 /* if we're running as a server (e.g., out of inetd) */
154 if ( ! isatty( 1 ) ) {
155 strcpy( tktpath, "/tmp/ud_tktXXXXXX" );
157 krb_set_tkt_string( tktpath );
160 kinited = valid_tgt( krbnames );
162 if ( hassimple && !kinited ) {
163 printf(" Which password would you like to use?\n");
164 printf(" 1 -> X.500 password\n");
166 printf(" 2 -> UMICH password (aka Uniqname or Kerberos password)\n");
168 printf(" 2 -> Kerberos password\n");
172 printf(" Enter 1 or 2: ");
175 fetch_buffer(buf, sizeof(buf), stdin);
177 } while (choice != 1 && choice != 2);
179 authmethod = (choice == 1 ? LDAP_AUTH_SIMPLE :
182 authmethod = LDAP_AUTH_KRBV4;
185 authmethod = LDAP_AUTH_SIMPLE;
186 (void) ldap_msgfree(mp);
190 * if they are already kinited, we don't need to ask for a
194 if ( authmethod == LDAP_AUTH_KRBV4 ) {
196 if ( krbnames[1] != NULL ) {
199 /* ask which one to use */
201 printf(" Which UMICH (aka Kerberos or uniqname) name would you like to use?\n");
203 printf(" Which Kerberos name would you like to use?\n");
205 for ( i = 0; krbnames[i] != NULL; i++ ) {
206 printf( " %d -> %s\n", i + 1,
210 printf(" Enter a number between 1 and %d: ", i );
213 fetch_buffer(buf, sizeof(buf), stdin);
214 ikrb = atoi(buf) - 1;
215 } while ( ikrb > i - 1 || ikrb < 0 );
221 if ( kinit( krbnames[ikrb] ) != 0 ) {
222 (void) ldap_value_free(rdns);
223 (void) ldap_value_free(krbnames);
229 authmethod = LDAP_AUTH_SIMPLE;
230 sprintf(prompt, " Enter your X.500 password: ");
232 passwd = mygetpass(prompt);
233 } while (passwd != NULL && *passwd == '\0');
234 if (passwd == NULL) {
235 (void) ldap_value_free(rdns);
240 (void) ldap_value_free(krbnames);
242 ldap_flush_cache( ld );
243 rc = ldap_bind_s(ld, Entry.DN, passwd, authmethod);
244 if (rc != LDAP_SUCCESS) {
245 if (ld->ld_errno == LDAP_NO_SUCH_ATTRIBUTE)
246 fprintf(stderr, " Entry has no password\n");
247 else if (ld->ld_errno == LDAP_INVALID_CREDENTIALS)
249 if ( authmethod == LDAP_AUTH_KRBV4 ) {
250 fprintf(stderr, " The Kerberos credentials are invalid.\n");
253 fprintf(stderr, " The password you provided is incorrect.\n");
258 ldap_perror(ld, "ldap_bind_s" );
259 (void) ldap_bind_s(ld, default_bind_object,
260 (char *) UD_BIND_CRED, LDAP_AUTH_SIMPLE);
261 if (default_bind_object == NULL)
264 set_bound_dn(default_bind_object);
265 bind_status = UD_NOT_BOUND;
267 printf(" Authentication failed.\n\n");
268 (void) ldap_value_free(rdns);
272 printf(" Authentication successful.\n\n");
275 set_bound_dn(Entry.DN);
276 bind_status = UD_BOUND;
278 (void) strcpy(password, passwd);
279 (void) ldap_value_free(rdns);
285 #define FIVEMINS ( 5 * 60 )
293 for ( p = s; *p != '\0'; ++p ) {
294 if ( islower( *p )) {
301 static valid_tgt( names )
305 char name[ ANAME_SZ ], inst[ INST_SZ ], realm[ REALM_SZ ];
308 for ( i = 0; names[i] != NULL; i++ ) {
309 if ( kname_parse( name, inst, realm, names[i] ) != KSUCCESS ) {
310 fprintf( stderr, "Bad format for krbName %s\n",
312 fprintf( stderr, "Contact x500@umich.edu\n" );
318 * realm must be uppercase for krb_ routines
321 #endif /* AFSKERBEROS */
324 * check ticket file for a valid ticket granting ticket
325 * my check is: have ticket granting ticket and it is good for
326 * at least 5 more minutes
328 if ( krb_get_cred( TGT, realm, realm,
329 &cred ) == KSUCCESS && time( 0 ) + FIVEMINS <
330 cred.issue_date + (u_char)cred.lifetime * FIVEMINS ) {
338 static char *kauth_name;
342 krbgetpass( user, inst, realm, pw, key )
343 char *user, *inst, *realm, *pw;
346 char *p, lcrealm[ REALM_SZ ], prompt[256], *passwd;
349 sprintf(prompt, " Enter the UMICH password (same as Uniqname or Kerberos password)\n for %s: ", kauth_name );
351 sprintf(prompt, " Enter Kerberos password for %s: ", kauth_name );
354 passwd = mygetpass(prompt);
355 } while (passwd != NULL && *passwd == '\0');
356 if (passwd == NULL) {
361 strcpy( lcrealm, realm );
362 for ( p = lcrealm; *p != '\0'; ++p ) {
363 if ( isupper( *p )) {
368 ka_StringToKey( passwd, lcrealm, key );
369 #else /* AFSKERBEROS */
370 string_to_key( passwd, key );
371 #endif /* AFSKERBEROS */
376 static kinit( kname )
380 char name[ ANAME_SZ ], inst[ INST_SZ ], realm[ REALM_SZ ];
384 if ( kname_parse( name, inst, realm, kname ) != KSUCCESS ) {
385 fprintf( stderr, "Bad format for krbName %s\n",
387 fprintf( stderr, "Contact x500@umich.edu\n" );
393 * realm must be uppercase for krb_ routines
396 #endif /* AFSKERBEROS */
398 rc = krb_get_in_tkt( name, inst, realm, TGT, realm,
399 DEFAULT_TKT_LIFE, krbgetpass, NULL, NULL );
401 if ( rc != KSUCCESS ) {
404 fprintf( stderr, "Can't contact Kerberos server for %s\n", realm );
407 fprintf( stderr, "%s: %s\n", name, krb_err_txt[ rc ] );
418 if ( *tktpath != '\0' ) {
424 static void set_bound_dn(s)
428 extern char *bound_dn;
430 if (bound_dn != NULL)
432 bound_dn = (s == NULL) ? NULL : strdup(s);