3 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
7 * Copyright (c) 1991, 1992 Regents of the University of Michigan.
10 * Redistribution and use in source and binary forms are permitted
11 * provided that this notice is preserved and that due credit is given
12 * to the University of Michigan at Ann Arbor. The name of the University
13 * may not be used to endorse or promote products derived from this
14 * software without specific prior written permission. This software
15 * is provided ``as is'' without express or implied warranty.
22 #include <ac/stdlib.h>
26 #include <ac/string.h>
28 #include <ac/unistd.h>
36 #include "ldap_defaults.h"
39 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
40 static char tktpath[20]; /* ticket file path */
42 static int valid_tgt();
45 static void set_bound_dn(char *s);
49 auth( char *who, int implicit )
51 int rc; /* return code from ldap_bind() */
52 char *passwd = NULL; /* returned by getpassphrase() */
53 char **rdns; /* for fiddling with the DN */
55 int name_provided; /* was a name passed in? */
57 struct passwd *pw; /* for getting user id */
62 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
63 char **krbnames; /* for kerberos names */
68 LDAPMessage *mp; /* returned from find() */
69 static char prompt[MED_BUF_SIZE]; /* place for us to sprintf the prompt */
70 static char name[MED_BUF_SIZE]; /* place to store the user's name */
71 static char password[MED_BUF_SIZE]; /* password entered by user */
75 fprintf(stderr, "auth(%s, NULL)\n", who);
77 name_provided = ( who != NULL );
80 * The user needs to bind. If <who> is not specified, we
81 * assume that authenticating as user id is what user wants.
83 if (who == NULL && implicit) {
87 if ((pw = getpwuid((uid_t)geteuid())) != (struct passwd *) NULL) {
88 sprintf(uidname, "uid=%s", pw->pw_name);
91 user = getenv("USER");
92 if(user == NULL) user = getenv("USERNAME");
93 if(user == NULL) user = getenv("LOGNAME");
96 sprintf(uidname, "uid=%s", user);
100 if(uidname[0] != '\0') {
107 printf( "You must first authenticate yourself to the Directory.\n" );
109 printf(" What is your name or uniqname? ");
111 printf(" What is your name or user id? ");
114 fetch_buffer(name, sizeof(name), stdin);
121 if (debug & D_AUTHENTICAT)
122 printf(" Authenticating as \"%s\"\n", who);
126 * Bail out if the name is bogus. If not, strip off the junk
127 * at the start of the DN, build a prompt, and get a password
128 * from the user. Then perform the ldap_bind().
130 if ((mp = find(who, TRUE)) == NULL) {
131 printf(" I could not find \"%s\" in the Directory.\n", who);
132 printf(" I used a search base of ");
133 printbase("", search_base);
136 if (debug & D_AUTHENTICAT)
137 printf(" Could not find \"%s\"\n", who);
143 * Fill in the Entry structure. May be handy later.
145 (void) parse_answer(mp);
147 rdns = ldap_explode_dn(Entry.DN, TRUE);
148 printf(" Authenticating to the directory as \"%s\"...\n", *rdns );
150 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
152 * First, if the user has a choice of auth methods, ask which
153 * one they want to use. if they want kerberos, ask which
154 * krbname they want to bind as.
157 if ( (krbnames = ldap_get_values( ld, mp, "krbName" )) != NULL ) {
158 int choice, hassimple;
160 hassimple = (ldap_compare_s( ld, Entry.DN,
161 "userPassword", "x" ) == LDAP_COMPARE_FALSE);
162 (void) ldap_msgfree(mp);
164 /* if we're running as a server (e.g., out of inetd) */
165 if ( ! isatty( 1 ) ) {
166 strcpy( tktpath, LDAP_TMPDIR LDAP_DEFSEP "ud_tktXXXXXX" );
168 krb_set_tkt_string( tktpath );
171 kinited = valid_tgt( krbnames );
173 if ( hassimple && !kinited ) {
174 printf(" Which password would you like to use?\n");
175 printf(" 1 -> LDAP password\n");
177 printf(" 2 -> UMICH password (aka Uniqname or Kerberos password)\n");
179 printf(" 2 -> Kerberos password\n");
183 printf(" Enter 1 or 2: ");
186 fetch_buffer(buf, sizeof(buf), stdin);
188 } while (choice != 1 && choice != 2);
190 authmethod = (choice == 1 ? LDAP_AUTH_SIMPLE :
193 authmethod = LDAP_AUTH_KRBV4;
196 authmethod = LDAP_AUTH_SIMPLE;
197 (void) ldap_msgfree(mp);
201 * if they are already kinited, we don't need to ask for a
205 if ( authmethod == LDAP_AUTH_KRBV4 ) {
207 if ( krbnames[1] != NULL ) {
210 /* ask which one to use */
212 printf(" Which UMICH (aka Kerberos or uniqname) name would you like to use?\n");
214 printf(" Which Kerberos name would you like to use?\n");
216 for ( i = 0; krbnames[i] != NULL; i++ ) {
217 printf( " %d -> %s\n", i + 1,
221 printf(" Enter a number between 1 and %d: ", i );
224 fetch_buffer(buf, sizeof(buf), stdin);
225 ikrb = atoi(buf) - 1;
226 } while ( ikrb > i - 1 || ikrb < 0 );
232 if ( kinit( krbnames[ikrb] ) != 0 ) {
233 (void) ldap_value_free(rdns);
234 (void) ldap_value_free(krbnames);
240 authmethod = LDAP_AUTH_SIMPLE;
241 sprintf(prompt, " Enter your LDAP password: ");
243 passwd = getpassphrase(prompt);
244 } while (passwd != NULL && *passwd == '\0');
245 if (passwd == NULL) {
246 (void) ldap_value_free(rdns);
249 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
251 (void) ldap_value_free(krbnames);
253 ldap_flush_cache( ld );
254 rc = ldap_bind_s(ld, Entry.DN, passwd, authmethod);
255 if (rc != LDAP_SUCCESS) {
257 ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);
258 if (ld_errno == LDAP_NO_SUCH_ATTRIBUTE)
259 fprintf(stderr, " Entry has no password\n");
260 else if (ld_errno == LDAP_INVALID_CREDENTIALS)
261 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
262 if ( authmethod == LDAP_AUTH_KRBV4 ) {
263 fprintf(stderr, " The Kerberos credentials are invalid.\n");
266 fprintf(stderr, " The password you provided is incorrect.\n");
267 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
271 ldap_perror(ld, "ldap_bind_s" );
272 (void) ldap_bind_s(ld, default_bind_object,
273 (char *) NULL, LDAP_AUTH_SIMPLE);
274 if (default_bind_object == NULL)
277 set_bound_dn(default_bind_object);
278 bind_status = UD_NOT_BOUND;
280 printf(" Authentication failed.\n\n");
281 (void) ldap_value_free(rdns);
285 printf(" Authentication successful.\n\n");
288 set_bound_dn(Entry.DN);
289 bind_status = UD_BOUND;
291 (void) strcpy(password, passwd);
292 (void) ldap_value_free(rdns);
296 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
298 #define FIVEMINS ( 5 * 60 )
302 valid_tgt( char **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" );
316 #ifdef HAVE_AFS_KERBEROS
318 * realm must be uppercase for krb_ routines
320 ldap_pvt_str2upper( realm );
321 #endif /* HAVE_AFS_KERBEROS */
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;
340 #ifndef HAVE_KTH_KERBEROS
344 krbgetpass( char *user, char *inst, char *realm, char *pw, C_Block key )
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 = getpassphrase(prompt);
355 } while (passwd != NULL && *passwd == '\0');
356 if (passwd == NULL) {
360 #ifdef HAVE_AFS_KERBEROS
361 strcpy( lcrealm, realm );
362 for ( p = lcrealm; *p != '\0'; ++p ) {
363 *p = TOLOWER( (unsigned char) *p );
366 ka_StringToKey( passwd, lcrealm, key );
367 #else /* HAVE_AFS_KERBEROS */
368 string_to_key( passwd, key );
369 #endif /* HAVE_AFS_KERBEROS */
373 #endif /* HAVE_KTH_KERBEROS */
379 char name[ ANAME_SZ ], inst[ INST_SZ ], realm[ REALM_SZ ];
383 if ( kname_parse( name, inst, realm, kname ) != KSUCCESS ) {
384 fprintf( stderr, "Bad format for krbName %s\n",
386 fprintf( stderr, "Contact x500@umich.edu\n" );
390 #ifdef HAVE_AFS_KERBEROS
391 /* realm must be uppercase for AFS krb_ routines */
392 ldap_pvt_str2upper( realm );
393 #endif /* HAVE_AFS_KERBEROS */
395 #ifdef HAVE_KTH_KERBEROS
396 /* Kth kerberos knows how to do both string to keys */
397 rc = krb_get_pw_in_tkt( name, inst, realm, TGT, realm,
398 DEFAULT_TKT_LIFE, 0 );
400 rc = krb_get_in_tkt( name, inst, realm, TGT, realm,
401 DEFAULT_TKT_LIFE, krbgetpass, NULL, NULL );
404 if ( rc != KSUCCESS ) {
407 fprintf( stderr, "Can't contact Kerberos server for %s\n", realm );
410 fprintf( stderr, "%s: %s\n", name, krb_err_txt[ rc ] );
420 destroy_tickets( void )
422 if ( *tktpath != '\0' ) {
429 set_bound_dn( char *s )
431 if (bound_dn != NULL)
433 bound_dn = (s == NULL) ? NULL : strdup(s);