gic_pwd.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Gets initial credentials upon authentication
*/
#include <k5-int.h>
#include <com_err.h>
#include <admin.h>
#include <locale.h>
#include <syslog.h>
/* Solaris Kerberos:
*
* Change Password functionality is handled by the libkadm5clnt.so.1 library in
* Solaris Kerberos. In order to avoid a circular dependency between that lib
* and the kerberos mech lib, we use the #pragma weak compiler directive.
* This way, when applications link with the libkadm5clnt.so.1 lib the circular
* dependancy between the two libs will be resolved.
*/
#pragma weak kadm5_get_cpw_host_srv_name
#pragma weak kadm5_init_with_password
#pragma weak kadm5_chpass_principal_util
char **);
extern kadm5_ret_t kadm5_init_with_password(char *, char *, char *,
char *, char **, char *, int);
static krb5_error_code
void *prompter_data,
void *gak_data)
{
char *clientstr;
char promptstr[1024];
/* If there's already a key of the correct etype, we're done.
If the etype is wrong, free the existing key, and make
a new one.
XXX This was the old behavior, and was wrong in hw preauth
cases. Is this new behavior -- always asking -- correct in all
cases? */
}
}
return(ret);
/* PROMPTER_INVOCATION */
1, &prompt)))) {
return(ret);
}
}
return(ret);
} else {
}
return(ret);
}
char *password,
void *data,
char *in_tkt_service,
{
int use_master;
int tries;
void *server_handle;
use_master = 0;
if (password) {
goto cleanup;
}
} else {
}
/* first try: get the requested tkt from any kdc */
krb5_get_as_key_password, (void *) &pw0,
use_master, &as_reply);
/* check for success */
if (ret == 0)
goto cleanup;
/* If all the kdc's are unavailable, or if the error was due to a
user interrupt, fail */
if ((ret == KRB5_KDC_UNREACH) ||
(ret == KRB5_PREAUTH_FAILED) ||
(ret == KRB5_LIBOS_PWDINTR) ||
(ret == KRB5_REALM_CANT_RESOLVE))
goto cleanup;
/* if the reply did not come from the master kdc, try again with
the master kdc */
if (!use_master) {
use_master = 1;
if (as_reply) {
}
krb5_get_as_key_password, (void *) &pw0,
use_master, &as_reply);
if (ret2 == 0) {
ret = 0;
goto cleanup;
}
/* if the master is unreachable, return the error from the
slave we were able to contact */
if ((ret2 == KRB5_KDC_UNREACH) ||
(ret2 == KRB5_REALM_CANT_RESOLVE) ||
(ret2 == KRB5_REALM_UNKNOWN))
goto cleanup;
}
#ifdef USE_LOGIN_LIBRARY
if (ret == KRB5KDC_ERR_KEY_EXP)
goto cleanup; /* Login library will deal appropriately with this error */
#endif
/* at this point, we have an error from the master. if the error
is not password expired, or if it is but there's no prompter,
return this error */
if ((ret != KRB5KDC_ERR_KEY_EXP) ||
goto cleanup;
/* ok, we have an expired password. Give the user a few chances
to change it */
/* Solaris Kerberos:
*
* Get the correct change password service principal name to use.
* This is necessary because SEAM based admin servers require
*/
"Kerberos mechanism library: Unable to get change password "
"service name for realm %s\n"), admin_realm);
goto cleanup;
} else {
ret=0;
}
/* extract the string version of the principal */
goto cleanup;
if (ret != 0) {
goto cleanup;
}
/* PROMPTER_INVOCATION */
goto cleanup;
} else {
int result_code;
NULL /* don't need pw back */,
sizeof(banner));
/* the change succeeded. go on */
if (result_code == 0) {
break;
}
/* set this in case the retry loop falls through */
if (result_code != KRB5_KPASSWD_SOFTERROR) {
goto cleanup;
}
}
}
if (ret)
goto cleanup;
/* the password change was successful. Get an initial ticket
from the master. this is the last try. the return from this
is final. */
krb5_get_as_key_password, (void *) &pw0,
use_master, &as_reply);
/* if getting the password was successful, then check to see if the
password is about to expire, and warn if so */
if (ret == 0) {
int hours;
/* XXX 7 days should be configurable. This is all pretty ad hoc,
and could probably be improved if I was willing to screw around
with timezones, etc. */
if (prompter &&
(in_tkt_service && cpw_service &&
(hours >= 0)) {
if (hours < 1)
"Warning: Your password will expire in less than one hour.");
else if (hours <= 48)
else
hours/24);
/* ignore an error here */
/* PROMPTER_INVOCATION */
} else if (prompter &&
(!in_tkt_service ||
/*
* Check the last_req fields
*/
char ts[256];
break;
break;
if (delta < 3600)
"Warning: Your password will expire in less than one "
"hour on %s", ts);
"Warning: Your password will expire in %d hour%s on %s",
else
"Warning: Your password will expire in %d days on %s",
/* ignore an error here */
/* PROMPTER_INVOCATION */
}
} /* prompter && !in_tkt_service */
}
if (as_reply)
return(ret);
}