compat_auth_plain dummy...
authorStefan Metzmacher <metze@sernet.de>
Fri, 14 Mar 2008 10:07:55 +0000 (11:07 +0100)
committerStefan Metzmacher <metze@sernet.de>
Fri, 2 May 2008 14:13:55 +0000 (16:13 +0200)
source/winbindd/winbindd_pam.c

index dafe92f5973e9a624e5a8720b7d55d85b7f6ab23..9637d2a8abfce38cc7c41b6b73ca50460f6fe02e 100644 (file)
@@ -1741,7 +1741,252 @@ static void ndr_child_auth_compat_auth_plain(struct winbindd_domain *domain,
                                             struct winbindd_cli_state *state,
                                             struct winbind_auth *r)
 {
-       r->out.result = WINBIND_STATUS_NOT_IMPLEMENTED;
+       NTSTATUS result = NT_STATUS_LOGON_FAILURE;
+       NTSTATUS krb5_result = NT_STATUS_OK;    
+       fstring name_domain, name_user;
+       fstring full_account_name;
+       struct netr_SamInfo3 *info3 = NULL;
+       struct winbind_auth_compat_auth_plain_req *in;
+
+       in = &r->in.req.compat_auth_plain;
+
+       DEBUG(3, ("comapt auth plain account[%s] domain[%s]\n",
+               in->account_name,
+               in->domain_name?in->domain_name:"(NULL)"));
+
+       /* Parse domain and username */
+       
+//     ws_name_return( state->request.data.auth.user, WB_REPLACE_CHAR );
+
+//     parse_domain_user(state->request.data.auth.user, name_domain, name_user);
+
+       if (domain->online == False) {
+               result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
+               if (domain->startup) {
+                       /* Logons are very important to users. If we're offline and
+                          we get a request within the first 30 seconds of startup,
+                          try very hard to find a DC and go online. */
+
+                       DEBUG(10,("winbindd_dual_pam_auth: domain: %s offline and auth "
+                               "request in startup mode.\n", domain->name ));
+
+                       winbindd_flush_negative_conn_cache(domain);
+                       result = init_dc_connection(domain);
+               }
+       }
+
+       DEBUG(10,("compat_auth_plain: domain: %s last was %s\n", domain->name, domain->online ? "online":"offline"));
+
+       /* Check for Kerberos authentication */
+       if (domain->online && (in->flags & WBFLAG_PAM_KRB5)) {
+       
+               result = winbindd_dual_pam_auth_kerberos(domain, state, &info3);
+               /* save for later */
+               krb5_result = result;
+               
+
+               if (NT_STATUS_IS_OK(result)) {
+                       DEBUG(10,("winbindd_dual_pam_auth_kerberos succeeded\n"));
+                       goto process_result;
+               } else {
+                       DEBUG(10,("winbindd_dual_pam_auth_kerberos failed: %s\n", nt_errstr(result)));
+               }
+
+               if (NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS) ||
+                   NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT) ||
+                   NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
+                       DEBUG(10,("winbindd_dual_pam_auth_kerberos setting domain to offline\n"));
+                       set_domain_offline( domain );
+                       goto cached_logon;                      
+               }
+
+               /* there are quite some NT_STATUS errors where there is no
+                * point in retrying with a samlogon, we explictly have to take
+                * care not to increase the bad logon counter on the DC */
+
+               if (NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_DISABLED) ||
+                   NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_EXPIRED) ||
+                   NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_LOCKED_OUT) ||
+                   NT_STATUS_EQUAL(result, NT_STATUS_INVALID_LOGON_HOURS) ||
+                   NT_STATUS_EQUAL(result, NT_STATUS_INVALID_WORKSTATION) ||
+                   NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE) ||
+                   NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER) ||
+                   NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_EXPIRED) ||
+                   NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_MUST_CHANGE) ||
+                   NT_STATUS_EQUAL(result, NT_STATUS_WRONG_PASSWORD)) {
+                       goto process_result;
+               }
+               
+               if (in->flags & WBFLAG_PAM_FALLBACK_AFTER_KRB5) {
+                       DEBUG(3,("falling back to samlogon\n"));
+                       goto sam_logon;
+               } else {
+                       goto cached_logon;
+               }
+       }
+
+sam_logon:
+       /* Check for Samlogon authentication */
+       if (domain->online) {
+               result = winbindd_dual_pam_auth_samlogon(domain, state, &info3);
+       
+               if (NT_STATUS_IS_OK(result)) {
+                       DEBUG(10,("winbindd_dual_pam_auth_samlogon succeeded\n"));
+                       /* add the Krb5 err if we have one */
+                       if ( NT_STATUS_EQUAL(krb5_result, NT_STATUS_TIME_DIFFERENCE_AT_DC ) ) {
+                               info3->base.user_flags |= LOGON_KRB5_FAIL_CLOCK_SKEW;
+                       }
+                       goto process_result;
+               } 
+
+                       DEBUG(10,("winbindd_dual_pam_auth_samlogon failed: %s\n", 
+                         nt_errstr(result)));
+
+               if (NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS) ||
+                   NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT) ||
+                   NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) 
+               {
+                       DEBUG(10,("winbindd_dual_pam_auth_samlogon setting domain to offline\n"));
+                       set_domain_offline( domain );
+                       goto cached_logon;                      
+               }
+
+                       if (domain->online) {
+                               /* We're still online - fail. */
+                               goto done;
+                       }
+       }
+
+cached_logon:
+       /* Check for Cached logons */
+       if (!domain->online && (in->flags & WBFLAG_PAM_CACHED_LOGIN) && 
+           lp_winbind_offline_logon()) {
+       
+               result = winbindd_dual_pam_auth_cached(domain, state, &info3);
+
+               if (NT_STATUS_IS_OK(result)) {
+                       DEBUG(10,("winbindd_dual_pam_auth_cached succeeded\n"));
+                       goto process_result;
+               } else {
+                       DEBUG(10,("winbindd_dual_pam_auth_cached failed: %s\n", nt_errstr(result)));
+                       goto done;
+               }
+       }
+
+process_result:
+
+       if (NT_STATUS_IS_OK(result)) {
+       
+               DOM_SID user_sid;
+
+               /* In all codepaths where result == NT_STATUS_OK info3 must have
+                  been initialized. */
+               if (!info3) {
+                       result = NT_STATUS_INTERNAL_ERROR;
+                       goto done;
+               }
+
+               netsamlogon_cache_store(name_user, info3);
+               wcache_invalidate_samlogon(find_domain_from_name(name_domain), info3);
+
+               /* save name_to_sid info as early as possible (only if
+                  this is our primary domain so we don't invalidate
+                  the cache entry by storing the seq_num for the wrong
+                  domain). */
+               if ( domain->primary ) {                        
+                       sid_compose(&user_sid, info3->base.domain_sid,
+                                   info3->base.rid);
+                       cache_name2sid(domain, name_domain, name_user, 
+                                      SID_NAME_USER, &user_sid);
+               }
+               
+               /* Check if the user is in the right group */
+
+               result = check_info3_in_groups(state->mem_ctx, info3,
+                                              in->num_require_membership_of_sids,
+                                              in->require_membership_of_sids);
+               if (!NT_STATUS_IS_OK(result)) {
+//                     DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n",
+//                               state->request.data.auth.user, 
+//                               state->request.data.auth.require_membership_of_sid));
+                       goto done;
+               }
+
+               result = append_data(state, info3, name_domain, name_user);
+               if (!NT_STATUS_IS_OK(result)) {
+                       goto done;
+               }
+
+               if ((in->flags & WBFLAG_PAM_CACHED_LOGIN)) {
+
+                       /* Store in-memory creds for single-signon using ntlm_auth. */
+                       result = winbindd_add_memory_creds(full_account_name,
+                                                       get_uid_from_state(state),
+                                                       in->password);
+
+                       if (!NT_STATUS_IS_OK(result)) {
+                               DEBUG(10,("Failed to store memory creds: %s\n", nt_errstr(result)));
+                               goto done;
+                       }
+
+                       if (lp_winbind_offline_logon()) {
+                               result = winbindd_store_creds(domain,
+                                                     state->mem_ctx,
+                                                     full_account_name,
+                                                     in->password,
+                                                     info3, NULL);
+                               if (!NT_STATUS_IS_OK(result)) {
+
+                                       /* Release refcount. */
+                                       winbindd_delete_memory_creds(full_account_name);
+
+                                       DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result)));
+                                       goto done;
+                               }
+                       }
+               }
+
+
+               if (state->request.flags & WBFLAG_PAM_GET_PWD_POLICY) {
+                       result = fillup_password_policy(domain, state);
+
+                       if (!NT_STATUS_IS_OK(result) 
+                           && !NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) ) 
+                       {
+                               DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(result)));
+                               goto done;
+                       }
+               }
+
+               result = NT_STATUS_OK;          
+       }
+
+done:
+       /* give us a more useful (more correct?) error code */
+       if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ||
+           (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
+               result = NT_STATUS_NO_LOGON_SERVERS;
+       }
+       
+       state->response.data.auth.nt_status = NT_STATUS_V(result);
+       fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
+
+       /* we might have given a more useful error above */
+       if (!*state->response.data.auth.error_string) 
+               fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
+       state->response.data.auth.pam_error = nt_status_to_pam(result);
+
+       DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authentication for user %s returned %s (PAM: %d)\n", 
+             state->request.data.auth.user, 
+             state->response.data.auth.nt_status_string,
+             state->response.data.auth.pam_error));          
+
+       if (!NT_STATUS_IS_OK(result)) {
+               r->out.result = WINBIND_STATUS_FOOBAR;
+               return;
+       }
+
+       r->out.result = WINBIND_STATUS_OK;
 }