msktpass.cpp (msktutil-1.1.tar.bz2) | : | msktpass.cpp (msktutil-1.2.1) | ||
---|---|---|---|---|
skipping to change at line 77 | skipping to change at line 77 | |||
} | } | |||
while (!(have_symbol && have_number && have_lower && have_upper)) { | while (!(have_symbol && have_number && have_lower && have_upper)) { | |||
have_symbol = 0; | have_symbol = 0; | |||
have_number = 0; | have_number = 0; | |||
have_upper = 0; | have_upper = 0; | |||
have_lower = 0; | have_lower = 0; | |||
for (i = 0; i < PASSWORD_LEN; i++) { | for (i = 0; i < PASSWORD_LEN; i++) { | |||
curr = 0; | curr = 0; | |||
while (curr < 33 || curr > 126) { | while (curr < 33 || curr > 126) { | |||
if ((curr = getc(fp)) == EOF) { | if ((curr = getc(fp)) == EOF) { | |||
error_exit("failed to read from /dev/urandom"); | error_exit("Failed to read from /dev/urandom"); | |||
} | } | |||
curr &= 0x7f; | curr &= 0x7f; | |||
chars_used++; | chars_used++; | |||
} | } | |||
have_symbol |= (curr >= 33 && curr <= 47); | have_symbol |= (curr >= 33 && curr <= 47); | |||
have_symbol |= (curr >= 91 && curr <= 96); | have_symbol |= (curr >= 91 && curr <= 96); | |||
have_symbol |= (curr >= 123 && curr <= 126); | have_symbol |= (curr >= 123 && curr <= 126); | |||
have_symbol |= (curr >= 58 && curr <= 64); | have_symbol |= (curr >= 58 && curr <= 64); | |||
have_number |= (curr >= 48 && curr <= 57); | have_number |= (curr >= 48 && curr <= 57); | |||
have_upper |= (curr >= 65 && curr <= 90); | have_upper |= (curr >= 65 && curr <= 90); | |||
have_lower |= (curr >= 97 && curr <= 122); | have_lower |= (curr >= 97 && curr <= 122); | |||
flags->password[i] = (char) curr; | flags->password[i] = (char) curr; | |||
} | } | |||
} | } | |||
fclose(fp); | fclose(fp); | |||
VERBOSE(" Characters read from /dev/urandom = %d", chars_used); | VERBOSE("Characters read from /dev/urandom: %d", chars_used); | |||
return 0; | return 0; | |||
} | } | |||
/* Try to set the the new Samba secret to <password>. */ | /* Try to set the the new Samba secret to <flags->password>. */ | |||
static int set_samba_secret(const std::string& password) | static int set_samba_secret(msktutil_flags *flags) | |||
{ | { | |||
VERBOSE("Setting samba machine trust account password"); | VERBOSE("Setting samba machine trust account password using command: %s", | |||
flags->samba_cmd.c_str()); | ||||
FILE *pipe; | ||||
pipe = popen(flags->samba_cmd.c_str(), "w"); | ||||
FILE *pipe = popen("net changesecretpw -f -i", "w"); | ||||
if (pipe == NULL) { | if (pipe == NULL) { | |||
error_exit( "could not run samba net command"); | fprintf(stdout, | |||
"Could not execute command: %s\n", | ||||
flags->samba_cmd.c_str() | ||||
); | ||||
return 1; | ||||
} | } | |||
size_t len = password.length(); | size_t len = flags->password.length(); | |||
if (fwrite(password.c_str(), sizeof(char), len, pipe) != len) { | if (fwrite(flags->password.c_str(), sizeof(char), len, pipe) != len) { | |||
error_exit( "write error putting password to samba net command"); | fprintf(stdout, | |||
"Write error passing password to command: %s\n", | ||||
flags->samba_cmd.c_str() | ||||
); | ||||
return 1; | ||||
} | } | |||
int rc = pclose(pipe); | int rc = pclose(pipe); | |||
if (rc != 0) { | if (rc != 0) { | |||
fprintf(stdout, | fprintf(stderr, | |||
"Setting samba secret failed with error code %d\n", | "WARNING: Setting samba secret failed with error code %d\n", | |||
rc | rc | |||
); | ); | |||
return 1; | return 1; | |||
} | } | |||
VERBOSE("Successfully set samba machine trust account password"); | VERBOSE("Successfully set samba machine trust account password"); | |||
return 0; | return 0; | |||
} | } | |||
int set_password(msktutil_flags *flags) | int set_password(msktutil_flags *flags) | |||
{ | { | |||
int ret; | int ret; | |||
krb5_data resp_code_string; | krb5_data resp_code_string; | |||
krb5_data resp_string; | krb5_data resp_string; | |||
int response = 0; | int response = 0; | |||
std::string old_pwdLastSet; | ||||
/* Zero out these data structures, because we attempt to free them | /* Zero out these data structures, because we attempt to free them | |||
* below, and sometimes, upon error conditions, the called API | * below, and sometimes, upon error conditions, the called API | |||
* hasn't set them itself. */ | * hasn't set them itself. */ | |||
resp_string.data = NULL; | resp_string.data = NULL; | |||
resp_string.length = 0; | resp_string.length = 0; | |||
resp_code_string.data = NULL; | resp_code_string.data = NULL; | |||
resp_code_string.length = 0; | resp_code_string.length = 0; | |||
if (flags->use_service_account) { | if (flags->use_service_account) { | |||
VERBOSE("Attempting to reset service account's password"); | VERBOSE("Attempting to reset service account's password"); | |||
} else { | } else { | |||
VERBOSE("Attempting to reset computer's password"); | VERBOSE("Attempting to reset computer's password"); | |||
} | } | |||
if (flags->auth_type == AUTH_FROM_USER_CREDS) { | if (flags->auth_type == AUTH_FROM_USER_CREDS) { | |||
VERBOSE("Try change password using user's ticket cache"); | VERBOSE("Try change password using user's ticket cache"); | |||
KRB5CCache ccache(KRB5CCache::defaultName()); | KRB5CCache ccache(KRB5CCache::defaultName()); | |||
KRB5Principal principal(flags->sAMAccountName); | KRB5Principal principal(flags->sAMAccountName); | |||
old_pwdLastSet = ldap_get_pwdLastSet(flags); | ||||
ret = krb5_set_password_using_ccache(g_context, | ret = krb5_set_password_using_ccache(g_context, | |||
ccache.get(), | ccache.get(), | |||
const_cast<char*>(flags->password.c _str()), | const_cast<char*>(flags->password.c _str()), | |||
principal.get(), | principal.get(), | |||
&response, | &response, | |||
&resp_code_string, | &resp_code_string, | |||
&resp_string); | &resp_string); | |||
krb5_free_data_contents(g_context, &resp_string); | krb5_free_data_contents(g_context, &resp_string); | |||
if (!ret && response) { | if (!ret && response) { | |||
skipping to change at line 181 | skipping to change at line 190 | |||
} | } | |||
krb5_free_data_contents(g_context, &resp_code_string); | krb5_free_data_contents(g_context, &resp_code_string); | |||
if (ret) { | if (ret) { | |||
if (!response && ret == KRB5KRB_AP_ERR_BADADDR) { | if (!response && ret == KRB5KRB_AP_ERR_BADADDR) { | |||
VERBOSE("krb5_set_password_using_ccache: password changed " | VERBOSE("krb5_set_password_using_ccache: password changed " | |||
"successfully, but sender IP in KRB-PRIV failed " | "successfully, but sender IP in KRB-PRIV failed " | |||
"validation"); | "validation"); | |||
if (!flags->server_behind_nat) { | if (!flags->server_behind_nat) { | |||
fprintf(stderr, | fprintf(stderr, | |||
"Error: krb5_set_password_using_ccache " | "Error: krb5_set_password_using_ccache " | |||
"failed (%s)\n", | "failed: %s\n", | |||
error_message(ret) | error_message(ret) | |||
); | ); | |||
return ret; | return ret; | |||
} | } | |||
} else { | } else { | |||
fprintf(stderr, | fprintf(stderr, | |||
"Error: krb5_set_password_using_ccache failed (%s)\n", | "Error: krb5_set_password_using_ccache failed: %s\n", | |||
error_message(ret) | error_message(ret) | |||
); | ); | |||
return ret; | return ret; | |||
} | } | |||
} | } | |||
} else { | } else { | |||
KRB5Creds creds; | KRB5Creds creds; | |||
/* Use the machine's credentials */ | /* Use the machine's credentials */ | |||
if (flags->auth_type == AUTH_FROM_SAM_KEYTAB || | if (flags->auth_type == AUTH_FROM_SAM_KEYTAB || | |||
flags->auth_type == AUTH_FROM_SAM_UPPERCASE_KEYTAB || | flags->auth_type == AUTH_FROM_SAM_UPPERCASE_KEYTAB || | |||
skipping to change at line 211 | skipping to change at line 220 | |||
std::string princ_name; | std::string princ_name; | |||
if (flags->auth_type == AUTH_FROM_SAM_KEYTAB) { | if (flags->auth_type == AUTH_FROM_SAM_KEYTAB) { | |||
princ_name = flags->sAMAccountName; | princ_name = flags->sAMAccountName; | |||
} else if (flags->auth_type == AUTH_FROM_SAM_UPPERCASE_KEYTAB) { | } else if (flags->auth_type == AUTH_FROM_SAM_UPPERCASE_KEYTAB) { | |||
princ_name = flags->sAMAccountName_uppercase; | princ_name = flags->sAMAccountName_uppercase; | |||
} else if (flags->auth_type == AUTH_FROM_EXPLICIT_KEYTAB) { | } else if (flags->auth_type == AUTH_FROM_EXPLICIT_KEYTAB) { | |||
princ_name = flags->keytab_auth_princ; | princ_name = flags->keytab_auth_princ; | |||
} else { | } else { | |||
princ_name = "host/" + flags->hostname; | princ_name = "host/" + flags->hostname; | |||
} | } | |||
VERBOSE("Try using keytab for %s to change password", | VERBOSE("Trying to use keytab for %s to change password", | |||
princ_name.c_str()); | princ_name.c_str()); | |||
KRB5Keytab keytab(flags->keytab_readname); | KRB5Keytab keytab(flags->keytab_readname); | |||
KRB5Principal principal(princ_name); | KRB5Principal principal(princ_name); | |||
KRB5Creds local_creds(principal, keytab, "kadmin/changepw"); | KRB5Creds local_creds(principal, keytab, "kadmin/changepw"); | |||
creds.move_from(local_creds); | creds.move_from(local_creds); | |||
} else if (flags->auth_type == AUTH_FROM_PASSWORD) { | } else if (flags->auth_type == AUTH_FROM_PASSWORD) { | |||
VERBOSE("Try using default password for %s to change password", | VERBOSE("Trying to use default password for %s to change password", | |||
flags->sAMAccountName.c_str()); | flags->sAMAccountName.c_str()); | |||
KRB5Principal principal(flags->sAMAccountName); | KRB5Principal principal(flags->sAMAccountName); | |||
KRB5Creds local_creds(principal, | KRB5Creds local_creds(principal, | |||
create_default_machine_password( | create_default_machine_password( | |||
flags->sAMAccountName), | flags->sAMAccountName), | |||
"kadmin/changepw"); | "kadmin/changepw"); | |||
creds.move_from(local_creds); | creds.move_from(local_creds); | |||
} else if ((flags->auth_type == AUTH_FROM_SUPPLIED_PASSWORD) || | } else if ((flags->auth_type == AUTH_FROM_SUPPLIED_PASSWORD) || | |||
(flags->auth_type == AUTH_FROM_SUPPLIED_EXPIRED_PASSWORD)) { | (flags->auth_type == AUTH_FROM_SUPPLIED_EXPIRED_PASSWORD)) { | |||
VERBOSE("Try using supplied password for %s to change password", | VERBOSE("Trying to use supplied password for %s to change password", | |||
flags->sAMAccountName.c_str()); | flags->sAMAccountName.c_str()); | |||
KRB5Principal principal(flags->sAMAccountName); | KRB5Principal principal(flags->sAMAccountName); | |||
KRB5Creds local_creds(principal, | KRB5Creds local_creds(principal, | |||
flags->old_account_password, | flags->old_account_password, | |||
"kadmin/changepw"); | "kadmin/changepw"); | |||
creds.move_from(local_creds); | creds.move_from(local_creds); | |||
} else /* shouldn't happen */ | } else /* shouldn't happen */ | |||
throw Exception("Error: unknown auth_type."); | throw Exception("Error: unknown auth_type"); | |||
if (flags->auth_type != AUTH_FROM_SUPPLIED_EXPIRED_PASSWORD) { | ||||
old_pwdLastSet = ldap_get_pwdLastSet(flags); | ||||
} | ||||
ret = krb5_change_password(g_context, | ret = krb5_change_password(g_context, | |||
creds.get(), | creds.get(), | |||
const_cast<char*>(flags->password.c_str()), | const_cast<char*>(flags->password.c_str()), | |||
&response, | &response, | |||
&resp_code_string, | &resp_code_string, | |||
&resp_string); | &resp_string); | |||
krb5_free_data_contents(g_context, &resp_string); | krb5_free_data_contents(g_context, &resp_string); | |||
if (response) { | if (response) { | |||
skipping to change at line 267 | skipping to change at line 272 | |||
return response; | return response; | |||
} | } | |||
krb5_free_data_contents(g_context, &resp_code_string); | krb5_free_data_contents(g_context, &resp_code_string); | |||
if (ret) { | if (ret) { | |||
if (!response && ret == KRB5KRB_AP_ERR_BADADDR) { | if (!response && ret == KRB5KRB_AP_ERR_BADADDR) { | |||
VERBOSE("krb5_change_password: password changed " | VERBOSE("krb5_change_password: password changed " | |||
"successfully, but sender IP in KRB-PRIV " | "successfully, but sender IP in KRB-PRIV " | |||
"failed validation"); | "failed validation"); | |||
if (!flags->server_behind_nat) { | if (!flags->server_behind_nat) { | |||
fprintf(stderr, | fprintf(stderr, | |||
"Error: krb5_change_password failed (%s)\n", | "Error: krb5_change_password failed: %s\n", | |||
error_message(ret) | error_message(ret) | |||
); | ); | |||
return ret; | return ret; | |||
} | } | |||
} else { | } else { | |||
fprintf(stderr, | fprintf(stderr, | |||
"Error: krb5_change_password failed (%s)\n", | "Error: krb5_change_password failed: %s\n", | |||
error_message(ret) | error_message(ret) | |||
); | ); | |||
return ret; | return ret; | |||
} | } | |||
} | } | |||
} | } | |||
VERBOSE("Successfully set password"); | VERBOSE("Successfully set password"); | |||
if (!flags->set_samba_secret) { | if (flags->set_samba_secret) { | |||
return 0; | /* At this point, we've already set the new password in AD, and there's | |||
* no way to roll back for us because we don't know the old password. | ||||
* Therefore, even if we fail to propagate the new password to Samba, | ||||
* we still need to carry on, and write out the new keys to the keytab. | ||||
* Failing here is not an option, so ignore the return value from | ||||
* set_samba_secret(), and proceed normally. (The function has already | ||||
* notified on stderr if a failure had occurred.) | ||||
*/ | ||||
(void) set_samba_secret(flags); | ||||
} | } | |||
return set_samba_secret(flags->password); | return 0; | |||
} | } | |||
End of changes. 20 change blocks. | ||||
29 lines changed or deleted | 42 lines changed or added |