diff options
Diffstat (limited to 'crypto/heimdal/lib/krb5/changepw.c')
-rw-r--r-- | crypto/heimdal/lib/krb5/changepw.c | 205 |
1 files changed, 101 insertions, 104 deletions
diff --git a/crypto/heimdal/lib/krb5/changepw.c b/crypto/heimdal/lib/krb5/changepw.c index 309e972..35534f4 100644 --- a/crypto/heimdal/lib/krb5/changepw.c +++ b/crypto/heimdal/lib/krb5/changepw.c @@ -33,54 +33,13 @@ #include <krb5_locl.h> -RCSID("$Id: changepw.c,v 1.32 2001/05/14 22:49:55 assar Exp $"); - -static krb5_error_code -get_kdc_address (krb5_context context, - krb5_realm realm, - struct addrinfo **ai, - char **ret_host) -{ - krb5_error_code ret; - char **hostlist; - int port = 0; - int error; - char *host; - int save_errno; - - ret = krb5_get_krb_changepw_hst (context, - &realm, - &hostlist); - if (ret) - return ret; - - host = strdup(*hostlist); - krb5_free_krbhst(context, hostlist); - if (host == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); - return ENOMEM; - } - - port = ntohs(krb5_getportbyname (context, "kpasswd", "udp", KPASSWD_PORT)); - error = roken_getaddrinfo_hostspec2(host, SOCK_DGRAM, port, ai); - - if(error) { - save_errno = errno; - krb5_set_error_string(context, "resolving %s: %s", - host, gai_strerror(error)); - return krb5_eai_to_heim_errno(error, save_errno); - } - *ret_host = host; - return 0; -} +RCSID("$Id: changepw.c,v 1.34 2001/09/27 01:29:12 assar Exp $"); static krb5_error_code send_request (krb5_context context, krb5_auth_context *auth_context, krb5_creds *creds, int sock, - struct sockaddr *sa, - int sa_size, char *passwd, const char *host) { @@ -128,8 +87,8 @@ send_request (krb5_context context, *p++ = (ap_req_data.length >> 0) & 0xFF; memset(&msghdr, 0, sizeof(msghdr)); - msghdr.msg_name = (void *)sa; - msghdr.msg_namelen = sa_size; + msghdr.msg_name = NULL; + msghdr.msg_namelen = 0; msghdr.msg_iov = iov; msghdr.msg_iovlen = sizeof(iov)/sizeof(*iov); #if 0 @@ -294,96 +253,134 @@ krb5_change_password (krb5_context context, { krb5_error_code ret; krb5_auth_context auth_context = NULL; + krb5_krbhst_handle handle = NULL; + krb5_krbhst_info *hi; int sock; int i; - struct addrinfo *ai, *a; int done = 0; - char *host = NULL; + krb5_realm realm = creds->client->realm; ret = krb5_auth_con_init (context, &auth_context); if (ret) return ret; - ret = get_kdc_address (context, creds->client->realm, &ai, &host); + krb5_auth_con_setflags (context, auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE); + + ret = krb5_krbhst_init (context, realm, KRB5_KRBHST_CHANGEPW, &handle); if (ret) goto out; - for (a = ai; !done && a != NULL; a = a->ai_next) { - int replied = 0; + while (krb5_krbhst_next(context, handle, &hi) == 0) { + struct addrinfo *ai, *a; - sock = socket (a->ai_family, a->ai_socktype, a->ai_protocol); - if (sock < 0) + ret = krb5_krbhst_get_addrinfo(context, hi, &ai); + if (ret) continue; - for (i = 0; !done && i < 5; ++i) { - fd_set fdset; - struct timeval tv; - - if (!replied) { - replied = 0; - ret = send_request (context, - &auth_context, - creds, - sock, - a->ai_addr, - a->ai_addrlen, - newpw, - host); - if (ret) { - close(sock); - goto out; - } - } - - if (sock >= FD_SETSIZE) { - krb5_set_error_string(context, "fd %d too large", sock); - ret = ERANGE; + for (a = ai; !done && a != NULL; a = a->ai_next) { + int replied = 0; + + sock = socket (a->ai_family, a->ai_socktype, a->ai_protocol); + if (sock < 0) + continue; + + ret = connect(sock, a->ai_addr, a->ai_addrlen); + if (ret < 0) { close (sock); goto out; } - FD_ZERO(&fdset); - FD_SET(sock, &fdset); - tv.tv_usec = 0; - tv.tv_sec = 1 + (1 << i); - - ret = select (sock + 1, &fdset, NULL, NULL, &tv); - if (ret < 0 && errno != EINTR) { - close(sock); + ret = krb5_auth_con_genaddrs (context, auth_context, sock, + KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR); + if (ret) { + close (sock); goto out; } - if (ret == 1) { - ret = process_reply (context, - auth_context, - sock, - result_code, - result_code_string, - result_string, - host); - if (ret == 0) - done = 1; - else if (i > 0 && ret == KRB5KRB_AP_ERR_MUT_FAIL) - replied = 1; - } else { - ret = KRB5_KDC_UNREACH; + + for (i = 0; !done && i < 5; ++i) { + fd_set fdset; + struct timeval tv; + + if (!replied) { + replied = 0; + ret = send_request (context, + &auth_context, + creds, + sock, + newpw, + hi->hostname); + if (ret) { + close(sock); + goto out; + } + } + + if (sock >= FD_SETSIZE) { + krb5_set_error_string(context, "fd %d too large", sock); + ret = ERANGE; + close (sock); + goto out; + } + + FD_ZERO(&fdset); + FD_SET(sock, &fdset); + tv.tv_usec = 0; + tv.tv_sec = 1 + (1 << i); + + ret = select (sock + 1, &fdset, NULL, NULL, &tv); + if (ret < 0 && errno != EINTR) { + close(sock); + goto out; + } + if (ret == 1) { + ret = process_reply (context, + auth_context, + sock, + result_code, + result_code_string, + result_string, + hi->hostname); + if (ret == 0) + done = 1; + else if (i > 0 && ret == KRB5KRB_AP_ERR_MUT_FAIL) + replied = 1; + } else { + ret = KRB5_KDC_UNREACH; + } } + close (sock); } - close (sock); } - freeaddrinfo (ai); -out: + out: + krb5_krbhst_free (context, handle); krb5_auth_con_free (context, auth_context); - free (host); if (done) return 0; else { if (ret == KRB5_KDC_UNREACH) krb5_set_error_string(context, - "failed to reach kpasswd server %s " - "in realm %s", - host, creds->client->realm); - + "unable to reach any changepw server " + " in realm %s", realm); return ret; } } + +const char * +krb5_passwd_result_to_string (krb5_context context, + int result) +{ + static const char *strings[] = { + "Success", + "Malformed", + "Hard error", + "Auth error", + "Soft error" + }; + + if (result < 0 || result > KRB5_KPASSWD_SOFTERROR) + return "unknown result code"; + else + return strings[result]; +} |