Added another authentication interface to winbindd. The Challenge Response
authorTim Potter <tpot@samba.org>
Wed, 22 Aug 2001 02:48:16 +0000 (02:48 +0000)
committerTim Potter <tpot@samba.org>
Wed, 22 Aug 2001 02:48:16 +0000 (02:48 +0000)
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)

source3/nsswitch/wbinfo.c
source3/nsswitch/winbindd.c
source3/nsswitch/winbindd_nss.h
source3/nsswitch/winbindd_pam.c
source3/nsswitch/winbindd_proto.h
source3/nsswitch/winbindd_util.c

index 9d3568417f44e7c1c3e89ef6971083e0ff33d0ba..2e3991b97b02abd26c35aa37ccedbf2eca97000d 100644 (file)
@@ -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:
index 0824b77294ef563edd56d226f34f4b7a0f1335f2..4c82c9f3af64b667b3f47ab0d176ec9280003c30 100644 (file)
@@ -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 */
index aedbaaf1fd9579b5659123087f1f2ab36673e648..8e2eaf7edef832f9be1c07a5d3e19dc7eb26d7fa 100644 (file)
@@ -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;
index 4dc08c608658dfbf4bafe14143ef0d6541199956..e595bb0796d243e4396d87333e888dc50c943ab8 100644 (file)
@@ -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)
index 11a3bc4f8649f36dc4f71479993e288f04e63f7a..3c61b1f872936ba021aa7a12b1f1569cd0df448b 100644 (file)
@@ -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);
index bdcf076acc4f38d5c4f71aa424a52a0390c2f470..75ddb6bc09c17de198ff76dfaaf3d12ebd1efb6c 100644 (file)
@@ -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 */