From 7c9e3fd7814cade61c67afe8d528a3175bf3b0e0 Mon Sep 17 00:00:00 2001 From: Assar Westerlund Date: Tue, 20 Jan 1998 21:59:33 +0000 Subject: [PATCH] rewritten to use the kadm5 API git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@4304 ec53bebd-3082-4978-b11e-865c3cabbd6b --- kpasswd/kpasswdd.c | 251 ++++++++++++++++----------------------------- 1 file changed, 89 insertions(+), 162 deletions(-) diff --git a/kpasswd/kpasswdd.c b/kpasswd/kpasswdd.c index 1543004e5..dda291db0 100644 --- a/kpasswd/kpasswdd.c +++ b/kpasswd/kpasswdd.c @@ -37,31 +37,15 @@ */ #include "kpasswd_locl.h" -#include +#include RCSID("$Id$"); static krb5_context context; +static void *kadm5_handle; static krb5_log_facility *log_facility; static sig_atomic_t exit_flag = 0; -#define KPASSWDD_LOG_ERR 0 -#define KPASSWDD_LOG_INFO 1 - -static void -syslog_and_die (const char *m, ...) -{ - va_list args; - - va_start(args, m); - krb5_vlog (context, log_facility, KPASSWDD_LOG_ERR, m, args); - va_end(args); - exit (1); -} - -static char *database = HDB_DEFAULT_DB; -static HDB *db; - static void send_reply (int s, struct sockaddr *sa, @@ -112,9 +96,7 @@ send_reply (int s, iov[2].iov_len = rest->length; if (sendmsg (s, &msghdr, 0) < 0) - krb5_log (context, log_facility, KPASSWDD_LOG_ERR, - "sendmsg: %s", - strerror(errno)); + krb5_warn (context, errno, "sendmsg"); } static int @@ -131,8 +113,7 @@ make_result (krb5_data *data, expl); if (data->data == NULL) { - krb5_log (context, log_facility, KPASSWDD_LOG_ERR, - "Out of memory generating error reply"); + krb5_warnx (context, "Out of memory generating error reply"); return 1; } return 0; @@ -164,9 +145,7 @@ reply_error (krb5_principal server, &error_data); krb5_data_free (&e_data); if (ret) { - krb5_log (context, log_facility, KPASSWDD_LOG_ERR, - "Could not even generate error reply: %s", - krb5_get_err_text (context, ret)); + krb5_warn (context, ret, "Could not even generate error reply"); return; } send_reply (s, sa, sa_size, NULL, &error_data); @@ -190,9 +169,7 @@ reply_priv (krb5_auth_context auth_context, &auth_context, &ap_rep_data); if (ret) { - krb5_log (context, log_facility, KPASSWDD_LOG_ERR, - "Could not even generate error reply: %s", - krb5_get_err_text (context, ret)); + krb5_warn (context, ret, "Could not even generate error reply"); return; } @@ -206,9 +183,7 @@ reply_priv (krb5_auth_context auth_context, NULL); krb5_data_free (&e_data); if (ret) { - krb5_log (context, log_facility, KPASSWDD_LOG_ERR, - "Could not even generate error reply: %s", - krb5_get_err_text (context, ret)); + krb5_warn (context, ret, "Could not even generate error reply"); return; } send_reply (s, sa, sa_size, &ap_rep_data, &krb_priv_data); @@ -235,129 +210,91 @@ change (krb5_auth_context auth_context, { krb5_error_code ret; char *c; - hdb_entry ent; + kadm5_principal_ent_rec ent; + krb5_key_data *kd; krb5_data salt; - krb5_keyblock new_keyblock, *old_keyblock; + krb5_keyblock new_keyblock; char *pwd_reason; + int unchanged; krb5_unparse_name (context, principal, &c); - krb5_log (context, log_facility, KPASSWDD_LOG_INFO, - "Changing password for %s", c); + krb5_warnx (context, "Changing password for %s", c); free (c); pwd_reason = passwd_quality_check (pwd_data); if (pwd_reason != NULL ) { - krb5_log (context, log_facility, - KPASSWDD_LOG_ERR, pwd_reason); + krb5_warnx (context, pwd_reason); reply_priv (auth_context, s, sa, sa_size, 4, pwd_reason); return; } - ret = db->open(context, db, O_RDWR, 0600); + ret = kadm5_get_principal (kadm5_handle, + principal, + &ent, + KADM5_KEY_DATA); if (ret) { - krb5_log (context, log_facility, KPASSWDD_LOG_ERR, - "hdb_open: %s", krb5_get_err_text(context, ret)); - reply_priv (auth_context, s, sa, sa_size, 2, "hdb_open failed"); + krb5_warn (context, ret, "kadm5_get_principal"); + reply_priv (auth_context, s, sa, sa_size, 2, + "kadm5_get_principal failed"); return; } - krb5_copy_principal (context, principal, &ent.principal); - - ret = db->fetch (context, db, &ent); - - switch (ret) { - case HDB_ERR_NOENTRY: - krb5_log (context, log_facility, KPASSWDD_LOG_ERR, - "not found in database"); - reply_priv (auth_context, s, sa, sa_size, 2, - "entry not found in database"); - goto out; - case 0: - break; - default : - krb5_log (context, log_facility, KPASSWDD_LOG_ERR, - "dbfetch: %s", krb5_get_err_text(context, ret)); - reply_priv (auth_context, s, sa, sa_size, 2, - "db_fetch failed"); - goto out; - } - /* * Compare with the first key to see if it already has been * changed. If it hasn't, store the new key in the database and * string2key all the rest of them. */ - krb5_data_zero (&salt); - krb5_get_salt (principal, &salt); + kd = &ent.key_data[0]; + + salt.length = kd->key_data_length[1]; + salt.data = kd->key_data_contents[1]; + memset (&new_keyblock, 0, sizeof(new_keyblock)); - old_keyblock = &ent.keys.val[0].key; - krb5_string_to_key_data (pwd_data, &salt, - old_keyblock->keytype, /* XXX */ + krb5_string_to_key_data (pwd_data, + &salt, + kd->key_data_type[0], &new_keyblock); - if (new_keyblock.keytype == old_keyblock->keytype - && new_keyblock.keyvalue.length == old_keyblock->keyvalue.length - && memcmp (new_keyblock.keyvalue.data, - old_keyblock->keyvalue.data, - new_keyblock.keyvalue.length) == 0) { - ret = 0; - } else { - Event *e; - int i; + unchanged = new_keyblock.keytype == kd->key_data_type[0] + && new_keyblock.keyvalue.length == kd->key_data_length[0] + && memcmp(new_keyblock.keyvalue.data, + kd->key_data_contents[0], + new_keyblock.keyvalue.length) == 0; - free_EncryptionKey (old_keyblock); - memset (old_keyblock, 0, sizeof(*old_keyblock)); - old_keyblock->keytype = new_keyblock.keytype; - krb5_data_copy (&old_keyblock->keyvalue, - new_keyblock.keyvalue.data, - new_keyblock.keyvalue.length); - - for(i = 1; i < ent.keys.len; ++i) { - free_Key (&ent.keys.val[i]); - krb5_string_to_key_data (pwd_data, - &salt, - ent.keys.val[i].key.keytype, - &ent.keys.val[i].key); - } - - ent.kvno++; - e = malloc(sizeof(*e)); - e->time = time(NULL); - krb5_copy_principal (context, principal, &e->principal); - if (ent.modified_by) { - free_Event (ent.modified_by); - free (ent.modified_by); - } - ent.modified_by = e; - if (ent.pw_end){ - int t = krb5_config_get_time(context, NULL, - "libdefaults", - "pw_expiration", NULL); - if(t > 0) - *ent.pw_end = e->time + t; - else{ - free(ent.pw_end); - ent.pw_end = NULL; - } - } - ret = db->store (context, db, 1, &ent); - } - krb5_data_free (&salt); krb5_free_keyblock_contents (context, &new_keyblock); - if (ret) { - krb5_log (context, log_facility, KPASSWDD_LOG_ERR, - "dbstore: %s", krb5_get_err_text (context, ret)); - reply_priv (auth_context, s, sa, sa_size, 2, - "db_store failed"); + if (unchanged) { + ret = 0; } else { - reply_priv (auth_context, s, sa, sa_size, 0, "password changed"); + char *tmp; + + tmp = malloc (pwd_data->length + 1); + if (tmp == NULL) { + krb5_warnx (context, "malloc: out of memory"); + reply_priv (auth_context, s, sa, sa_size, 2, + "malloc failed"); + goto out; + } + memcpy (tmp, pwd_data->data, pwd_data->length); + tmp[pwd_data->length] = '\0'; + + ret = kadm5_chpass_principal (kadm5_handle, + principal, + tmp); + memset (tmp, 0, pwd_data->length); + free (tmp); + if (ret) { + krb5_warn (context, ret, "kadm5_s_chpass_principal"); + reply_priv (auth_context, s, sa, sa_size, 2, + "change failed"); + goto out; + } } + reply_priv (auth_context, s, sa, sa_size, 0, "password changed"); out: - hdb_free_entry (context, &ent); - db->close (context, db); + kadm5_free_principal_ent (kadm5_handle, &ent); } static int @@ -380,14 +317,12 @@ verify (krb5_auth_context *auth_context, pkt_ver = (msg[2] << 8) | (msg[3]); ap_req_len = (msg[4] << 8) | (msg[5]); if (pkt_len != len) { - krb5_log (context, log_facility, KPASSWDD_LOG_ERR, - "Strange len: %d != %d", pkt_len, len); + krb5_warnx (context, "Strange len: %d != %d", pkt_len, len); reply_error (server, s, sa, sa_size, 0, 1, "bad length"); return 1; } if (pkt_ver != 0x0001) { - krb5_log (context, log_facility, KPASSWDD_LOG_ERR, - "Bad version (%d)", pkt_ver); + krb5_warnx (context, "Bad version (%d)", pkt_ver); reply_error (server, s, sa, sa_size, 0, 1, "bad version"); return 1; } @@ -403,15 +338,13 @@ verify (krb5_auth_context *auth_context, NULL, ticket); if (ret) { - krb5_log (context, log_facility, KPASSWDD_LOG_ERR, "krb5_rd_req: %s", - krb5_get_err_text(context, ret)); + krb5_warn (context, ret, "krb5_rd_req"); reply_error (server, s, sa, sa_size, ret, 3, "rd_req failed"); return 1; } if (!(*ticket)->ticket.flags.initial) { - krb5_log (context, log_facility, KPASSWDD_LOG_ERR, - "initial flag not set"); + krb5_warnx (context, "initial flag not set"); reply_error (server, s, sa, sa_size, ret, 1, "initial flag not set"); goto out; @@ -426,8 +359,7 @@ verify (krb5_auth_context *auth_context, NULL); if (ret) { - krb5_log (context, log_facility, KPASSWDD_LOG_ERR, "krb5_rd_priv: %s", - krb5_get_err_text(context, ret)); + krb5_warn (context, ret, "krb5_rd_priv"); reply_error (server, s, sa, sa_size, ret, 3, "rd_priv failed"); goto out; } @@ -456,9 +388,7 @@ process (krb5_principal server, ret = krb5_auth_con_init (context, &auth_context); if (ret) { - krb5_log (context, log_facility, KPASSWDD_LOG_ERR, - "krb5_auth_con_init: %s", - krb5_get_err_text(context, ret)); + krb5_warn (context, ret, "krb5_auth_con_init"); return; } @@ -467,9 +397,7 @@ process (krb5_principal server, ret = krb5_sockaddr2address (sa, &other_addr); if (ret) { - krb5_log (context, log_facility, KPASSWDD_LOG_ERR, - "krb5_sockaddr2address: %s", - krb5_get_err_text(context, ret)); + krb5_warn (context, ret, "krb5_sockaddr2address"); goto out; } @@ -479,9 +407,7 @@ process (krb5_principal server, &other_addr); krb5_free_address (context, &other_addr); if (ret) { - krb5_log (context, log_facility, KPASSWDD_LOG_ERR, - "krb5_auth_con_setaddr: %s", - krb5_get_err_text(context, ret)); + krb5_warn (context, ret, "krb5_auth_con_setaddr"); goto out; } @@ -519,13 +445,12 @@ doit (int port) sa_max_size = krb5_max_sockaddr_size (); sa_buf = malloc (sa_max_size); if (sa_buf == NULL) - syslog_and_die ("out of memory"); + krb5_errx (context, 1, "out of memory"); sa = (struct sockaddr *)sa_buf; ret = krb5_get_default_realm (context, &realm); if (ret) - syslog_and_die ("krb5_get_default_realm: %s", - krb5_get_err_text(context, ret)); + krb5_err (context, 1, ret, "krb5_get_default_realm"); ret = krb5_build_principal (context, &server, @@ -535,19 +460,19 @@ doit (int port) "changepw", NULL); if (ret) - syslog_and_die ("krb5_build_principal_ext: %s", - krb5_get_err_text(context, ret)); + krb5_err (context, 1, ret, "krb5_build_principal"); free (realm); ret = krb5_get_all_client_addrs (&addrs); if (ret) - syslog_and_die ("krb5_get_all_clients_addrs: %s", - krb5_get_err_text(context, ret)); + krb5_err (context, 1, ret, "krb5_get_all_client_addrs"); n = addrs.len; sockets = malloc (n * sizeof(*sockets)); + if (sockets == NULL) + krb5_errx (context, 1, "out of memory"); maxfd = 0; FD_ZERO(&real_fdset); for (i = 0; i < n; ++i) { @@ -557,10 +482,9 @@ doit (int port) sockets[i] = socket (sa->sa_family, SOCK_DGRAM, 0); if (sockets[i] < 0) - syslog_and_die ("socket: %m"); - + krb5_err (context, 1, errno, "socket"); if (bind (sockets[i], sa, sa_size) < 0) - syslog_and_die ("bind: %m"); + krb5_err (context, 1, errno, "bind"); maxfd = max (maxfd, sockets[i]); FD_SET(sockets[i], &real_fdset); } @@ -574,7 +498,7 @@ doit (int port) if (errno == EINTR) continue; else - syslog_and_die ("select: %m"); + krb5_err (context, 1, errno, "select"); for (i = 0; i < n; ++i) if (FD_ISSET(sockets[i], &fdset)) { u_char buf[BUFSIZ]; @@ -586,7 +510,7 @@ doit (int port) if(errno == EINTR) break; else - syslog_and_die ("recvfrom: %m"); + krb5_err (context, 1, errno, "recvfrom"); process (server, sockets[i], &addrs.val[i], @@ -611,21 +535,24 @@ int main (int argc, char **argv) { krb5_error_code ret; - char *keyfile = NULL; + kadm5_config_params conf; krb5_init_context (&context); set_progname (argv[0]); krb5_openlog (context, "kpasswdd", &log_facility); + krb5_set_warn_dest(context, log_facility); - ret = hdb_create (context, &db, database); + memset (&conf, 0, sizeof(conf)); + + ret = kadm5_s_init_with_password_ctx(context, + KADM5_ADMIN_SERVICE, + "password", + KADM5_ADMIN_SERVICE, + &conf, 0, 0, + &kadm5_handle); if (ret) - syslog_and_die ("Failed to open database %s: %s", - database, krb5_get_err_text(context, ret)); - ret = hdb_set_master_key(context, db, keyfile); - if (ret) - syslog_and_die ("Failed to set master key: %s", - krb5_get_err_text(context, ret)); + krb5_err (context, 1, ret, "kadm5_s_init_with_password_ctx"); #ifdef HAVE_SIGACTION {