diff options
author | Tim Potter <tpot@samba.org> | 2001-08-22 02:48:16 +0000 |
---|---|---|
committer | Tim Potter <tpot@samba.org> | 2001-08-22 02:48:16 +0000 |
commit | b0f167cdf2942ddaeaa03032542e74345ce81308 (patch) | |
tree | 64362bf09a3267cfeff0c5066b4706f28e19887e /source3/nsswitch | |
parent | 8d9cdf0d749413c1575b6cc44bfeed3f0605a526 (diff) | |
download | samba-b0f167cdf2942ddaeaa03032542e74345ce81308.tar.gz samba-b0f167cdf2942ddaeaa03032542e74345ce81308.tar.bz2 samba-b0f167cdf2942ddaeaa03032542e74345ce81308.zip |
Added another authentication interface to winbindd. The Challenge Response
Authentication Protocol (CRAP) takes a tuple of (username, random
challenge, encrypted lm password, encrypted nt password) where the
passwords are encrypted with the random challenge ala ntlmssp.
(This used to be commit 11f72a78e3a16bbb17b576d80b47a9eb818ee428)
Diffstat (limited to 'source3/nsswitch')
-rw-r--r-- | source3/nsswitch/wbinfo.c | 131 | ||||
-rw-r--r-- | source3/nsswitch/winbindd.c | 1 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_nss.h | 9 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_pam.c | 73 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_proto.h | 21 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_util.c | 1 |
6 files changed, 210 insertions, 26 deletions
diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c index 9d3568417f..2e3991b97b 100644 --- a/source3/nsswitch/wbinfo.c +++ b/source3/nsswitch/wbinfo.c @@ -27,8 +27,9 @@ /* Prototypes from common.h */ -int winbindd_request(int req_type, struct winbindd_request *request, - struct winbindd_response *response); +enum nss_status winbindd_request(int req_type, + struct winbindd_request *request, + struct winbindd_response *response); /* List groups a user is a member of */ @@ -260,6 +261,85 @@ static BOOL wbinfo_lookupname(char *name) return True; } +/* Authenticate a user with a plaintext password */ + +static BOOL wbinfo_auth(char *username) +{ + struct winbindd_request request; + struct winbindd_response response; + enum winbindd_result result; + char *p; + + /* Send off request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + p = strchr(username, '%'); + + if (p) { + *p = 0; + fstrcpy(request.data.auth.user, username); + fstrcpy(request.data.auth.pass, p + 1); + *p = '%'; + } else + fstrcpy(request.data.auth.user, username); + + result = winbindd_request(WINBINDD_PAM_AUTH, &request, &response); + + /* Display response */ + + printf("plaintext password authentication %s\n", + (result == WINBINDD_OK) ? "succeeded" : "failed"); + + return result == WINBINDD_OK; +} + +/* Authenticate a user with a challenge/response */ + +static BOOL wbinfo_auth_crap(char *username) +{ + struct winbindd_request request; + struct winbindd_response response; + enum winbindd_result result; + fstring pass; + char *p; + + /* Send off request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + p = strchr(username, '%'); + + if (p) { + *p = 0; + fstrcpy(request.data.auth_crap.user, username); + fstrcpy(pass, p + 1); + *p = '%'; + } else + fstrcpy(request.data.auth_crap.user, username); + + generate_random_buffer(request.data.auth_crap.chal, 8, False); + + SMBencrypt(pass, request.data.auth_crap.chal, + request.data.auth_crap.lm_resp); + SMBNTencrypt(pass, request.data.auth_crap.chal, + request.data.auth_crap.nt_resp); + + request.data.auth_crap.lm_resp_len = 24; + request.data.auth_crap.nt_resp_len = 24; + + result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response); + + /* Display response */ + + printf("challenge/response password authentication %s\n", + (result == WINBINDD_OK) ? "succeeded" : "failed"); + + return result == WINBINDD_OK; +} + /* Print domain users */ static BOOL print_domain_users(void) @@ -322,18 +402,20 @@ static BOOL print_domain_groups(void) static void usage(void) { - printf("Usage: wbinfo -ug | -n name | -sSY sid | -UG uid/gid | -tm\n"); - printf("\t-u\tlists all domain users\n"); - printf("\t-g\tlists all domain groups\n"); - printf("\t-n name\tconverts name to sid\n"); - printf("\t-s sid\tconverts sid to name\n"); - printf("\t-U uid\tconverts uid to sid\n"); - printf("\t-G gid\tconverts gid to sid\n"); - printf("\t-S sid\tconverts sid to uid\n"); - printf("\t-Y sid\tconverts sid to gid\n"); - printf("\t-t\tcheck shared secret\n"); - printf("\t-m\tlist trusted domains\n"); - printf("\t-r user\tget user groups\n"); + printf("Usage: wbinfo -ug | -n name | -sSY sid | -UG uid/gid | -tm " + "| -a user%%password\n"); + printf("\t-u\t\t\tlists all domain users\n"); + printf("\t-g\t\t\tlists all domain groups\n"); + printf("\t-n name\t\t\tconverts name to sid\n"); + printf("\t-s sid\t\t\tconverts sid to name\n"); + printf("\t-U uid\t\t\tconverts uid to sid\n"); + printf("\t-G gid\t\t\tconverts gid to sid\n"); + printf("\t-S sid\t\t\tconverts sid to uid\n"); + printf("\t-Y sid\t\t\tconverts sid to gid\n"); + printf("\t-t\t\t\tcheck shared secret\n"); + printf("\t-m\t\t\tlist trusted domains\n"); + printf("\t-r user\t\t\tget user groups\n"); + printf("\t-a user%%password\tauthenticate user\n"); } /* Main program */ @@ -371,7 +453,7 @@ int main(int argc, char **argv) return 1; } - while ((opt = getopt(argc, argv, "ugs:n:U:G:S:Y:tmr:")) != EOF) { + while ((opt = getopt(argc, argv, "ugs:n:U:G:S:Y:tmr:a:")) != EOF) { switch (opt) { case 'u': if (!print_domain_users()) { @@ -444,7 +526,26 @@ int main(int argc, char **argv) return 1; } break; + case 'a': { + BOOL got_error = False; + + if (!wbinfo_auth(optarg)) { + printf("Could not authenticate user %s with " + "plaintext password\n", optarg); + got_error = True; + } + + if (!wbinfo_auth_crap(optarg)) { + printf("Could not authenticate user %s with " + "challenge/response\n", optarg); + got_error = True; + } + + if (got_error) + return 1; + break; + } /* Invalid option */ default: diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c index 0824b77294..4c82c9f3af 100644 --- a/source3/nsswitch/winbindd.c +++ b/source3/nsswitch/winbindd.c @@ -244,6 +244,7 @@ static struct dispatch_table dispatch_table[] = { /* PAM auth functions */ { WINBINDD_PAM_AUTH, winbindd_pam_auth }, + { WINBINDD_PAM_AUTH_CRAP, winbindd_pam_auth_crap }, { WINBINDD_PAM_CHAUTHTOK, winbindd_pam_chauthtok }, /* Enumeration functions */ diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h index aedbaaf1fd..8e2eaf7ede 100644 --- a/source3/nsswitch/winbindd_nss.h +++ b/source3/nsswitch/winbindd_nss.h @@ -55,6 +55,7 @@ enum winbindd_cmd { /* PAM authenticate and password change */ WINBINDD_PAM_AUTH, + WINBINDD_PAM_AUTH_CRAP, WINBINDD_PAM_CHAUTHTOK, /* List various things */ @@ -100,6 +101,14 @@ struct winbindd_request { fstring pass; } auth; /* pam_winbind auth module */ struct { + char chal[8]; + fstring user; + fstring lm_resp; + uint16 lm_resp_len; + fstring nt_resp; + uint16 nt_resp_len; + } auth_crap; + struct { fstring user; fstring oldpass; fstring newpass; diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index 4dc08c6086..e595bb0796 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -104,7 +104,7 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) generate_random_buffer( user_info.chal, 8, False); - if (state->request.data.auth.pass) { + if (state->request.data.auth.pass[0]) { SMBencrypt((uchar *)state->request.data.auth.pass, user_info.chal, local_lm_response); user_info.lm_resp.buffer = (uint8 *)local_lm_response; user_info.lm_resp.len = 24; @@ -136,6 +136,77 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) return result ? WINBINDD_OK : WINBINDD_ERROR; } +/* Challenge Response Authentication Protocol */ + +enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) +{ + BOOL result; + fstring name_domain, name_user; + unsigned char trust_passwd[16]; + time_t last_change_time; + auth_usersupplied_info user_info; + auth_serversupplied_info server_info; + AUTH_STR theirdomain, smb_username, wksta_name; + + DEBUG(3, ("[%5d]: pam auth crap %s\n", state->pid, + state->request.data.auth_crap.user)); + + /* Parse domain and username */ + + parse_domain_user(state->request.data.auth_crap.user, name_domain, + name_user); + + ZERO_STRUCT(user_info); + ZERO_STRUCT(theirdomain); + ZERO_STRUCT(smb_username); + ZERO_STRUCT(wksta_name); + + theirdomain.str = name_domain; + theirdomain.len = strlen(theirdomain.str); + + user_info.requested_domain = theirdomain; + user_info.domain = theirdomain; + + user_info.smb_username.str = name_user; + user_info.smb_username.len = strlen(name_user); + + user_info.requested_username.str = name_user; + user_info.requested_username.len = strlen(name_user); + + user_info.wksta_name.str = global_myname; + user_info.wksta_name.len = strlen(user_info.wksta_name.str); + + user_info.wksta_name = wksta_name; + + memcpy(user_info.chal, state->request.data.auth_crap.chal, 8); + + user_info.lm_resp.buffer = state->request.data.auth_crap.lm_resp; + user_info.nt_resp.buffer = state->request.data.auth_crap.nt_resp; + + user_info.lm_resp.len = 24; + user_info.nt_resp.len = 24; + + /* + * Get the machine account password for our primary domain + */ + + if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, &last_change_time)) + { + DEBUG(0, ("winbindd_pam_auth: could not fetch trust account password for domain %s\n", lp_workgroup())); + return WINBINDD_ERROR; + } + + /* So domain_client_validate() actually opens a new connection + for each authentication performed. This can theoretically + be optimised to use an already open IPC$ connection. */ + + result = (domain_client_validate(&user_info, &server_info, + server_state.controller, trust_passwd, + last_change_time) == NT_STATUS_NOPROBLEMO); + + return result ? WINBINDD_OK : WINBINDD_ERROR; +} + /* Change a user password */ enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state) diff --git a/source3/nsswitch/winbindd_proto.h b/source3/nsswitch/winbindd_proto.h index 11a3bc4f86..3c61b1f872 100644 --- a/source3/nsswitch/winbindd_proto.h +++ b/source3/nsswitch/winbindd_proto.h @@ -3,12 +3,12 @@ /* This file is automatically generated with "make proto". DO NOT EDIT */ -/*The following definitions come from nsswitch/winbindd.c */ +/* The following definitions come from nsswitch/winbindd.c */ void winbindd_dump_status(void); int main(int argc, char **argv); -/*The following definitions come from nsswitch/winbindd_cache.c */ +/* The following definitions come from nsswitch/winbindd_cache.c */ void winbindd_cache_init(void); void winbindd_store_user_cache(char *domain, @@ -46,7 +46,7 @@ BOOL winbindd_fetch_gid_cache_entry(char *domain_name, gid_t gid, void winbindd_flush_cache(void); void winbindd_cache_dump_status(void); -/*The following definitions come from nsswitch/winbindd_group.c */ +/* The following definitions come from nsswitch/winbindd_group.c */ enum winbindd_result winbindd_getgrnam_from_group(struct winbindd_cli_state *state); @@ -58,7 +58,7 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state); enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state); enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state); -/*The following definitions come from nsswitch/winbindd_idmap.c */ +/* The following definitions come from nsswitch/winbindd_idmap.c */ BOOL winbindd_idmap_get_uid_from_rid(char *domain_name, uint32 user_rid, uid_t *uid); @@ -73,21 +73,22 @@ BOOL winbindd_idmap_get_rid_from_gid(gid_t gid, uint32 *group_rid, BOOL winbindd_idmap_init(void); void winbindd_idmap_dump_status(void); -/*The following definitions come from nsswitch/winbindd_misc.c */ +/* The following definitions come from nsswitch/winbindd_misc.c */ BOOL _get_trust_account_password(char *domain, unsigned char *ret_pwd, - time_t *pass_last_set_time); + time_t *pass_last_set_time); enum winbindd_result winbindd_check_machine_acct( struct winbindd_cli_state *state); enum winbindd_result winbindd_list_trusted_domains(struct winbindd_cli_state *state); -/*The following definitions come from nsswitch/winbindd_pam.c */ +/* The following definitions come from nsswitch/winbindd_pam.c */ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) ; +enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) ; enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state); -/*The following definitions come from nsswitch/winbindd_sid.c */ +/* The following definitions come from nsswitch/winbindd_sid.c */ enum winbindd_result winbindd_lookupsid(struct winbindd_cli_state *state); enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state); @@ -96,7 +97,7 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state); enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state); enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state); -/*The following definitions come from nsswitch/winbindd_user.c */ +/* The following definitions come from nsswitch/winbindd_user.c */ enum winbindd_result winbindd_getpwnam_from_user(struct winbindd_cli_state *state) ; @@ -107,7 +108,7 @@ enum winbindd_result winbindd_endpwent(struct winbindd_cli_state *state); enum winbindd_result winbindd_getpwent(struct winbindd_cli_state *state); enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state); -/*The following definitions come from nsswitch/winbindd_util.c */ +/* The following definitions come from nsswitch/winbindd_util.c */ void debug_conn_state(void); BOOL domain_handles_open(struct winbindd_domain *domain); diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index bdcf076acc..75ddb6bc09 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -788,6 +788,7 @@ static struct cmdstr_table cmdstr_table[] = { /* PAM auth functions */ { WINBINDD_PAM_AUTH, "pam auth" }, + { WINBINDD_PAM_AUTH_CRAP, "pam auth crap" }, { WINBINDD_PAM_CHAUTHTOK, "pam chauthtok" }, /* List things */ |