Add password changing support.
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@4296 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
		| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska H<>gskolan | ||||
|  * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska H<>gskolan | ||||
|  * (Royal Institute of Technology, Stockholm, Sweden). | ||||
|  * All rights reserved. | ||||
|  *  | ||||
| @@ -40,13 +40,20 @@ | ||||
| #include <config.h> | ||||
| RCSID("$Id$"); | ||||
| #endif | ||||
| #include <ctype.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <siad.h> | ||||
| #include <pwd.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/socket.h> | ||||
| #include <netinet/in.h> | ||||
|  | ||||
| #include <krb.h> | ||||
| #include <kafs.h> | ||||
| #include <kadm.h> | ||||
| #include <kadm_err.h> | ||||
| #include <roken.h> | ||||
|  | ||||
|  | ||||
| #ifndef POSIX_GETPWNAM_R | ||||
| @@ -97,6 +104,12 @@ posix_getpwuid_r(uid_t uid, struct passwd *pwd, | ||||
|  | ||||
| #endif /* POSIX_GETPWNAM_R */ | ||||
|  | ||||
| #ifndef DEBUG | ||||
| #define SIA_DEBUG(X) | ||||
| #else | ||||
| #define SIA_DEBUG(X) warnx X | ||||
| #endif | ||||
|  | ||||
| struct state{ | ||||
|     char ticket[MaxPathLen]; | ||||
|     int valid; | ||||
| @@ -111,6 +124,7 @@ siad_init(void) | ||||
| int  | ||||
| siad_chk_invoker(void) | ||||
| { | ||||
|     SIA_DEBUG(("siad_chk_invoker")); | ||||
|     return SIADFAIL; | ||||
| } | ||||
|  | ||||
| @@ -118,6 +132,7 @@ int | ||||
| siad_ses_init(SIAENTITY *entity, int pkgind) | ||||
| { | ||||
|     struct state *s = malloc(sizeof(*s)); | ||||
|     SIA_DEBUG(("siad_ses_init")); | ||||
|     if(s == NULL) | ||||
| 	return SIADFAIL; | ||||
|     memset(s, 0, sizeof(*s)); | ||||
| @@ -128,6 +143,7 @@ siad_ses_init(SIAENTITY *entity, int pkgind) | ||||
| static int | ||||
| setup_name(SIAENTITY *e, prompt_t *p) | ||||
| { | ||||
|     SIA_DEBUG(("setup_name")); | ||||
|     e->name = malloc(SIANAMEMIN+1); | ||||
|     if(e->name == NULL) | ||||
| 	return SIADFAIL; | ||||
| @@ -142,6 +158,7 @@ setup_name(SIAENTITY *e, prompt_t *p) | ||||
| static int | ||||
| setup_password(SIAENTITY *e, prompt_t *p) | ||||
| { | ||||
|     SIA_DEBUG(("setup_password")); | ||||
|     e->password = malloc(SIAMXPASSWORD+1); | ||||
|     if(e->password == NULL) | ||||
| 	return SIADFAIL; | ||||
| @@ -163,6 +180,7 @@ common_auth(sia_collect_func_t *collect, | ||||
|     prompt_t prompts[2], *pr; | ||||
|     char *toname, *toinst; | ||||
|  | ||||
|     SIA_DEBUG(("common_auth")); | ||||
|     if((siastat == SIADSUCCESS) && (geteuid() == 0)) | ||||
| 	return SIADSUCCESS; | ||||
|     if(entity == NULL) | ||||
| @@ -262,6 +280,7 @@ siad_ses_authent(sia_collect_func_t *collect, | ||||
| 		 int siastat, | ||||
| 		 int pkgind) | ||||
| { | ||||
|     SIA_DEBUG(("siad_ses_authent")); | ||||
|     return common_auth(collect, entity, siastat, pkgind); | ||||
| } | ||||
|  | ||||
| @@ -269,6 +288,7 @@ int | ||||
| siad_ses_estab(sia_collect_func_t *collect,  | ||||
| 	       SIAENTITY *entity, int pkgind) | ||||
| { | ||||
|     SIA_DEBUG(("siad_ses_estab")); | ||||
|     return SIADFAIL; | ||||
| } | ||||
|  | ||||
| @@ -277,9 +297,9 @@ siad_ses_launch(sia_collect_func_t *collect, | ||||
| 		SIAENTITY *entity, | ||||
| 		int pkgind) | ||||
| { | ||||
|     char buf[MaxPathLen]; | ||||
|     static char env[MaxPathLen]; | ||||
|     struct state *s = (struct state*)entity->mech[pkgind]; | ||||
|     SIA_DEBUG(("siad_ses_launch")); | ||||
|     if(s->valid){ | ||||
| 	chown(s->ticket, entity->pwd->pw_uid, entity->pwd->pw_gid); | ||||
| 	snprintf(env, sizeof(env), "KRBTKFILE=%s", s->ticket); | ||||
| @@ -298,6 +318,7 @@ siad_ses_launch(sia_collect_func_t *collect, | ||||
| int  | ||||
| siad_ses_release(SIAENTITY *entity, int pkgind) | ||||
| { | ||||
|     SIA_DEBUG(("siad_ses_release")); | ||||
|     if(entity->mech[pkgind]) | ||||
| 	free(entity->mech[pkgind]); | ||||
|     return SIADSUCCESS; | ||||
| @@ -309,6 +330,7 @@ siad_ses_suauthent(sia_collect_func_t *collect, | ||||
| 		   int siastat, | ||||
| 		   int pkgind) | ||||
| { | ||||
|     SIA_DEBUG(("siad_ses_suauth")); | ||||
|     if(geteuid() != 0) | ||||
| 	return SIADFAIL; | ||||
|     if(entity->name == NULL) | ||||
| @@ -326,6 +348,7 @@ siad_ses_reauthent (sia_collect_func_t *collect, | ||||
| 			int siastat, | ||||
| 			int pkgind) | ||||
| { | ||||
|     SIA_DEBUG(("siad_ses_reauthent")); | ||||
|     return SIADFAIL; | ||||
| } | ||||
|  | ||||
| @@ -335,16 +358,160 @@ siad_chg_finger (sia_collect_func_t *collect, | ||||
| 		     int argc,  | ||||
| 		     char *argv[]) | ||||
| { | ||||
|     SIA_DEBUG(("siad_chg_finger")); | ||||
|     return SIADFAIL; | ||||
| } | ||||
|  | ||||
| int | ||||
| siad_chg_passwd (sia_collect_func_t *collect, | ||||
| 		     const char *username,  | ||||
| 		     int argc,  | ||||
| 		     char *argv[]) | ||||
| static void | ||||
| sia_message(sia_collect_func_t *collect, int rendition,  | ||||
| 	    const char *title, const char *message) | ||||
| { | ||||
|     return SIADFAIL; | ||||
|     prompt_t prompt; | ||||
|     prompt.prompt = (unsigned char*)message; | ||||
|     (*collect)(0, rendition, (unsigned char*)title, 1, &prompt); | ||||
| } | ||||
|  | ||||
| static int | ||||
| init_change(sia_collect_func_t *collect, krb_principal *princ) | ||||
| { | ||||
|     prompt_t prompt; | ||||
|     char old_pw[MAX_KPW_LEN+1]; | ||||
|     char *msg; | ||||
|     char tktstring[128]; | ||||
|     int ret; | ||||
|      | ||||
|     SIA_DEBUG(("init_change")); | ||||
|     prompt.prompt = (unsigned char*)"Old password: "; | ||||
|     prompt.result = (unsigned char*)old_pw; | ||||
|     prompt.min_result_length = 0; | ||||
|     prompt.max_result_length = sizeof(old_pw) - 1; | ||||
|     prompt.control_flags = SIARESINVIS; | ||||
|     asprintf(&msg, "Changing password for %s", krb_unparse_name(princ)); | ||||
|     if(msg == NULL){ | ||||
| 	SIA_DEBUG(("out of memory")); | ||||
| 	return SIADFAIL; | ||||
|     } | ||||
|     ret = (*collect)(60, SIAONELINER, (unsigned char*)msg, 1, &prompt); | ||||
|     free(msg); | ||||
|     SIA_DEBUG(("ret = %d", ret)); | ||||
|     if(ret != SIACOLSUCCESS) | ||||
| 	return SIADFAIL; | ||||
|     snprintf(tktstring, sizeof(tktstring),  | ||||
| 	     TKT_ROOT "_cpw_%u", (unsigned)getpid()); | ||||
|     krb_set_tkt_string(tktstring); | ||||
|      | ||||
|     ret = krb_get_pw_in_tkt(princ->name, princ->instance, princ->realm,  | ||||
| 			    PWSERV_NAME, KADM_SINST, 1, old_pw); | ||||
|     if (ret != KSUCCESS) { | ||||
| 	SIA_DEBUG(("krb_get_pw_in_tkt: %s", krb_get_err_text(ret))); | ||||
| 	if (ret == INTK_BADPW) | ||||
| 	    sia_message(collect, SIAWARNING, "", "Incorrect old password."); | ||||
| 	else | ||||
| 	    sia_message(collect, SIAWARNING, "", "Kerberos error."); | ||||
| 	memset(old_pw, 0, sizeof(old_pw)); | ||||
| 	return SIADFAIL; | ||||
|     } | ||||
|     if(chown(tktstring, getuid(), -1) < 0){ | ||||
| 	dest_tkt(); | ||||
| 	return SIADFAIL; | ||||
|     } | ||||
|     memset(old_pw, 0, sizeof(old_pw)); | ||||
|     return SIADSUCCESS; | ||||
| } | ||||
|  | ||||
| int | ||||
| siad_chg_password (sia_collect_func_t *collect, | ||||
| 		   const char *username,  | ||||
| 		   int argc,  | ||||
| 		   char *argv[]) | ||||
| { | ||||
|     prompt_t prompts[2]; | ||||
|     krb_principal princ; | ||||
|     int ret; | ||||
|     char new_pw1[MAX_KPW_LEN+1]; | ||||
|     char new_pw2[MAX_KPW_LEN+1]; | ||||
|     static struct error_table *et_list; | ||||
|  | ||||
|     set_progname(argv[0]); | ||||
|  | ||||
|     SIA_DEBUG(("siad_chg_password")); | ||||
|     if(collect == NULL) | ||||
| 	return SIADFAIL; | ||||
|  | ||||
|     if(username == NULL) | ||||
| 	username = getlogin(); | ||||
|  | ||||
|     ret = krb_parse_name(username, &princ); | ||||
|     if(ret) | ||||
| 	return SIADFAIL; | ||||
|     if(princ.realm[0] == '\0') | ||||
| 	krb_get_lrealm(princ.realm, 1); | ||||
|  | ||||
|     if(et_list == NULL) { | ||||
| 	initialize_kadm_error_table_r(&et_list); | ||||
| 	initialize_krb_error_table_r(&et_list); | ||||
|     } | ||||
|  | ||||
|     ret = init_change(collect, &princ); | ||||
|     if(ret != SIADSUCCESS) | ||||
| 	return ret; | ||||
|  | ||||
| again: | ||||
|     prompts[0].prompt = (unsigned char*)"New password: "; | ||||
|     prompts[0].result = (unsigned char*)new_pw1; | ||||
|     prompts[0].min_result_length = MIN_KPW_LEN; | ||||
|     prompts[0].max_result_length = sizeof(new_pw1) - 1; | ||||
|     prompts[0].control_flags = SIARESINVIS; | ||||
|     prompts[1].prompt = (unsigned char*)"Verify new password: "; | ||||
|     prompts[1].result = (unsigned char*)new_pw2; | ||||
|     prompts[1].min_result_length = MIN_KPW_LEN; | ||||
|     prompts[1].max_result_length = sizeof(new_pw2) - 1; | ||||
|     prompts[1].control_flags = SIARESINVIS; | ||||
|     if((*collect)(120, SIAFORM, (unsigned char*)"", 2, prompts) !=  | ||||
|        SIACOLSUCCESS) { | ||||
| 	dest_tkt(); | ||||
| 	return SIADFAIL; | ||||
|     } | ||||
|     if(strcmp(new_pw1, new_pw2) != 0){ | ||||
| 	sia_message(collect, SIAWARNING, "", "Password mismatch."); | ||||
| 	goto again; | ||||
|     } | ||||
|     ret = kadm_check_pw(new_pw1); | ||||
|     if(ret) { | ||||
| 	sia_message(collect, SIAWARNING, "", com_right(et_list, ret)); | ||||
| 	goto again; | ||||
|     } | ||||
|      | ||||
|     memset(new_pw2, 0, sizeof(new_pw2)); | ||||
|     ret = kadm_init_link (PWSERV_NAME, KRB_MASTER, princ.realm); | ||||
|     if (ret != KADM_SUCCESS) | ||||
| 	sia_message(collect, SIAWARNING, "Error initing kadmin connection",  | ||||
| 		    com_right(et_list, ret)); | ||||
|     else { | ||||
| 	des_cblock newkey; | ||||
| 	char *pw_msg; /* message from server */ | ||||
|  | ||||
| 	des_string_to_key(new_pw1, &newkey); | ||||
| 	ret = kadm_change_pw_plain((unsigned char*)&newkey, new_pw1, &pw_msg); | ||||
| 	memset(newkey, 0, sizeof(newkey)); | ||||
|        | ||||
| 	if (ret == KADM_INSECURE_PW) | ||||
| 	    sia_message(collect, SIAWARNING, "Insecure password", pw_msg); | ||||
| 	else if (ret != KADM_SUCCESS) | ||||
| 	    sia_message(collect, SIAWARNING, "Error changing password",  | ||||
| 			com_right(et_list, ret)); | ||||
|     } | ||||
|     memset(new_pw1, 0, sizeof(new_pw1)); | ||||
|  | ||||
|     if (ret != KADM_SUCCESS) | ||||
| 	sia_message(collect, SIAWARNING, "", "Password NOT changed."); | ||||
|     else | ||||
| 	sia_message(collect, SIAINFO, "", "Password changed."); | ||||
|      | ||||
|     dest_tkt(); | ||||
|     if(ret) | ||||
| 	return SIADFAIL; | ||||
|     return SIADSUCCESS; | ||||
| } | ||||
|  | ||||
| int | ||||
| @@ -441,5 +608,7 @@ siad_endgrent (struct sia_context *context) | ||||
| int | ||||
| siad_chk_user (const char *logname, int checkflag) | ||||
| { | ||||
|     return SIADFAIL; | ||||
|     if(checkflag != CHGPASSWD) | ||||
| 	return SIADFAIL; | ||||
|     return SIADSUCCESS; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Johan Danielsson
					Johan Danielsson