mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
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 11f72a78e3
)
This commit is contained in:
parent
8d9cdf0d74
commit
b0f167cdf2
@ -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:
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
@ -99,6 +100,14 @@ struct winbindd_request {
|
||||
fstring user;
|
||||
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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user