gic_pwd.c revision 5e01956f3000408c2a2c5a08c8d0acf2c2a9d8ee
/*
#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 *,
void **);
char *, char **, char *, unsigned int);
/*
* Solaris Kerberos:
* See the function's definition for the description of this interface.
*/
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,
{
/*
* Solaris Kerberos:
* We call our own private function that returns the as_reply back to
* the caller. This structure contains information, such as
* key-expiration and last-req fields. Entities such as pam_krb5 can
* The original "prompter" interface is not granular enough for PAM,
* as it will perform all passes w/o coordination with other modules.
*/
}
/*
* Solaris Kerberos:
* See krb5_get_init_creds_password()'s comments for the justification of this
* private function. Caller must free ptr_as_reply if non-NULL.
*/
char *password,
void *data,
char *in_tkt_service,
{
int use_master;
int tries;
void *server_handle;
use_master = 0;
goto cleanup;
}
} else {
}
"krb5_get_init_creds_password");
if (ret)
goto cleanup;
/* 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, or preauth errored out, 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 or reset the use_master flag */
if ((ret2 != KRB5_KDC_UNREACH) &&
(ret2 != KRB5_REALM_CANT_RESOLVE) &&
(ret2 != KRB5_REALM_UNKNOWN)) {
} else {
use_master = 0;
/* Solaris - if 2nd try failed, reset 1st err msg */
}
}
}
/* Solaris Kerberos: 163 resync */
/* #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;
/* historically the default has been to prompt for password change.
* if the change password prompt option has not been set, we continue
* to prompt. Prompting is only disabled if the option has been set
* and the value has been set to false.
*/
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;
&result_string)))
goto cleanup;
/* 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;
}
/* the error was soft, so try again */
/* 100 is I happen to know that no code_string will be longer
than 100 chars */
(int) result_string.length,
}
}
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 (err_msg_1)
/* 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 */
}
}
}
/*
* Solaris Kerberos:
* Argument, ptr_as_reply, being returned to caller if success and non-NULL.
*/
if (ptr_as_reply == NULL)
else
*ptr_as_reply = as_reply;
}
return(ret);
}
{
int i;
if (addrs)
if (ktypes) {
for (i=0; ktypes[i]; i++);
if (i)
}
if (pre_auth_types) {
for (i=0; pre_auth_types[i]; i++);
if (i)
}
else krb5_get_init_creds_opt_set_forwardable(opt, 0);
if (options&KDC_OPT_PROXIABLE)
else krb5_get_init_creds_opt_set_proxiable(opt, 0);
}
"krb5int_populate_gic_opt");
}
/*
Rewrites get_in_tkt in terms of newer get_init_creds API.
Attempts to get an initial ticket for creds->client to use server
creds->server, (realm is taken from creds->client), with options
options, and using creds->times.starttime, creds->times.endtime,
creds->times.renew_till as from, till, and rtime.
creds->times.renew_till is ignored unless the RENEWABLE option is requested.
If addrs is non-NULL, it is used for the addresses requested. If it is
null, the system standard addresses are used.
If password is non-NULL, it is converted using the cryptosystem entry
point for a string conversion routine, seeded with the client's name.
If password is passed as NULL, the password is read from the terminal,
and then converted into a key.
A succesful call will place the ticket in the credentials cache ccache.
returns system errors, encryption errors
*/
{
char pw0array[1024];
char * server;
int use_master = 0;
pw0array[0] = '\0';
if (password) {
return EINVAL;
} else {
}
if (retval)
return (retval);
if (retval) {
return (retval);
}
if (retval) {
return (retval);
}
/* store it in the ccache! */
if (ccache)
return (retval);
return retval;
}