From 5eef87b8b039c0f6b32005eb363ba4c9a2c2efaa Mon Sep 17 00:00:00 2001 From: Alexandra Ellwood Date: Tue, 2 Sep 2003 15:32:50 +0000 Subject: Added Apple password server support ticket: 1799 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@15803 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/kadm5/srv/svr_principal.c | 145 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) (limited to 'src/lib/kadm5/srv/svr_principal.c') diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c index c1b8bc59c9..1255e387b6 100644 --- a/src/lib/kadm5/srv/svr_principal.c +++ b/src/lib/kadm5/srv/svr_principal.c @@ -19,6 +19,9 @@ static char *rcsid = "$Header$"; #include "server_internal.h" #include #include +#ifdef USE_PASSWORD_SERVER +#include +#endif extern krb5_principal master_princ; extern krb5_principal hist_princ; @@ -1065,6 +1068,112 @@ static kadm5_ret_t add_to_history(krb5_context context, } #undef KADM_MOD +#ifdef USE_PASSWORD_SERVER + +/* FIXME: don't use global variable for this */ +krb5_boolean use_password_server = 0; + +static krb5_boolean +kadm5_use_password_server (void) +{ + return use_password_server; +} + +void +kadm5_set_use_password_server (void) +{ + use_password_server = 1; +} + +/* + * kadm5_launch_task () runs a program (task_path) to synchronize the + * Apple password server with the Kerberos database. Password server + * programs can receive arguments on the command line (task_argv) + * and a block of data via stdin (data_buffer). On success, they + * return one of the result codes listed in success_codes. + * + * Because a failure to communicate with the tool results in the + * password server falling out of sync with the database, + * kadm5_launch_task() always fails if it can't talk to the tool. + */ + +static kadm5_ret_t +kadm5_launch_task (krb5_context context, + const char *task_path, char * const task_argv[], + const char *data_buffer) +{ + kadm5_ret_t ret = 0; + int data_pipe[2]; + + if (data_buffer != NULL) { + ret = pipe (data_pipe); + if (ret) { ret = errno; } + } + + if (!ret) { + pid_t pid = fork (); + if (pid == -1) { + ret = errno; + } else if (pid == 0) { + /* The child: */ + + if (data_buffer != NULL) { + if (dup2 (data_pipe[0], STDIN_FILENO) == -1) { + _exit (1); + } + } else { + close (data_pipe[0]); + } + + close (data_pipe[1]); + + execv (task_path, task_argv); + + _exit (1); /* Fail if execv fails */ + } else { + /* The parent: */ + + if (data_buffer != NULL) { + /* Write out the buffer to the child */ + if (krb5_net_write (context, data_pipe[1], + data_buffer, strlen (data_buffer)) < 0) { + ret = errno; + } + } + + close (data_buffer[0]); + close (data_buffer[1]); + + if (!ret) { + int status = 0; + + waitpid (pid, &status, 0); + + /* fprintf (stderr, "Call \"%s\" returned status %d\n", argv[2], + WEXITSTATUS(status)); */ + + if (WIFEXITED (status)) { + /* task finished. Check return value */ + if ((WEXITSTATUS (status) != 0) && (WEXITSTATUS (status) != 252)) { + ret = KRB5KDC_ERR_POLICY; /* password change rejected */ + } + } else { + /* task crashed or was killed */ + ret = KRB5KRB_ERR_GENERIC; /* FIXME: better error */ + } + } else { + /* since the password write failed, just try and kill the child + * process in order to clean up (it may already be gone). */ + kill (pid, SIGKILL); + } + } + } + + return ret; +} + +#endif + kadm5_ret_t kadm5_chpass_principal(void *server_handle, krb5_principal principal, char *password) @@ -1193,6 +1302,42 @@ kadm5_chpass_principal_3(void *server_handle, kdb.pw_expiration = 0; } +#ifdef USE_PASSWORD_SERVER + if (kadm5_use_password_server () && + (krb5_princ_size (handle->context, principal) == 1)) { + krb5_data *princ = krb5_princ_component (handle->context, principal, 0); + const char *path = "/usr/sbin/mkpassdb"; + char *argv[] = { "mkpassdb", "-setpassword", NULL, NULL }; + char *pstring = NULL; + char pwbuf[256]; + int pwlen = strlen (password); + + if (pwlen > 254) pwlen = 254; + strncpy (pwbuf, password, pwlen); + pwbuf[pwlen] = '\n'; + pwbuf[pwlen + 1] = '\0'; + + if (!ret) { + pstring = malloc ((princ->length + 1) * sizeof (char)); + if (pstring == NULL) { ret = errno; } + } + + if (!ret) { + memcpy (pstring, princ->data, princ->length); + pstring [princ->length] = '\0'; + argv[2] = pstring; + + ret = kadm5_launch_task (handle->context, path, argv, pwbuf); + } + + if (pstring != NULL) + free (pstring); + + if (ret) + goto done; + } +#endif + ret = krb5_dbe_update_last_pwd_change(handle->context, &kdb, now); if (ret) goto done; -- cgit