summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/nsswitch/wbinfo.c131
-rw-r--r--source3/nsswitch/winbindd.c1
-rw-r--r--source3/nsswitch/winbindd_nss.h9
-rw-r--r--source3/nsswitch/winbindd_pam.c73
-rw-r--r--source3/nsswitch/winbindd_proto.h21
-rw-r--r--source3/nsswitch/winbindd_util.c1
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 */