Change the passdb interface to use allocated strings.
[ira/wip.git] / source3 / rpc_server / srv_netlog_nt.c
index e29d9393a662ef9c28eced7c6e739b94ca885d11..1ae1b65fddccf9b83c587b28b8b1f646a29f3448 100644 (file)
@@ -6,6 +6,7 @@
  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
  *  Copyright (C) Paul Ashton                       1997.
  *  Copyright (C) Jeremy Allison               1998-2001.
+ *  Copyirht  (C) Andrew Bartlett                   2001.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
 
 #include "includes.h"
 
-extern int DEBUGLEVEL;
-
-extern BOOL sam_logon_in_ssb;
-extern pstring samlogon_user;
 extern pstring global_myname;
 extern DOM_SID global_sam_sid;
 
@@ -76,26 +73,55 @@ NTSTATUS _net_logon_ctrl(pipes_struct *p, NET_Q_LOGON_CTRL *q_u,
        return r_u->status;
 }
 
+/****************************************************************************
+Send a message to smbd to do a sam synchronisation
+**************************************************************************/
+static void send_sync_message(void)
+{
+        TDB_CONTEXT *tdb;
+
+        tdb = tdb_open_log(lock_path("connections.tdb"), 0,
+                           TDB_DEFAULT, O_RDONLY, 0);
+
+        if (!tdb) {
+                DEBUG(3, ("send_sync_message(): failed to open connections "
+                          "database\n"));
+                return;
+        }
+
+        DEBUG(3, ("sending sam synchronisation message\n"));
+        
+        message_send_all(tdb, MSG_SMB_SAM_SYNC, NULL, 0, False, NULL);
+
+        tdb_close(tdb);
+}
+
 /*************************************************************************
  net_reply_logon_ctrl2:
  *************************************************************************/
 
 NTSTATUS _net_logon_ctrl2(pipes_struct *p, NET_Q_LOGON_CTRL2 *q_u, NET_R_LOGON_CTRL2 *r_u)
 {
-    /* lkclXXXX - guess what - absolutely no idea what these are! */
-    uint32 flags = 0x0;
-    uint32 pdc_connection_status = 0x0;
-    uint32 logon_attempts = 0x0;
-    uint32 tc_status = ERROR_NO_LOGON_SERVERS;
-    char *trusted_domain = "test_domain";
+        uint32 flags = 0x0;
+        uint32 pdc_connection_status = 0x0;
+        uint32 logon_attempts = 0x0;
+        uint32 tc_status = ERROR_NO_LOGON_SERVERS;
+        char *trusted_domain = "test_domain";
+
+        DEBUG(0, ("*** net long ctrl2 %d, %d, %d\n",
+                  q_u->function_code, q_u->query_level, q_u->switch_value));
 
        DEBUG(6,("_net_logon_ctrl2: %d\n", __LINE__));
 
+
        /* set up the Logon Control2 response */
        init_net_r_logon_ctrl2(r_u, q_u->query_level,
                               flags, pdc_connection_status, logon_attempts,
                               tc_status, trusted_domain);
 
+        if (lp_server_role() == ROLE_DOMAIN_BDC)
+                send_sync_message();
+
        DEBUG(6,("_net_logon_ctrl2: %d\n", __LINE__));
 
        return r_u->status;
@@ -142,7 +168,7 @@ static void init_net_r_srv_pwset(NET_R_SRV_PWSET *r_s,
 static BOOL get_md4pw(char *md4pw, char *mach_acct)
 {
        SAM_ACCOUNT *sampass = NULL;
-       uint8 *pass;
+       const uint8 *pass;
        BOOL ret;
 
 #if 0
@@ -163,7 +189,7 @@ static BOOL get_md4pw(char *md4pw, char *mach_acct)
        }
 #endif /* 0 */
 
-       if(!pdb_init_sam(&sampass))
+       if(!NT_STATUS_IS_OK(pdb_init_sam(&sampass)))
                return False;
 
        /* JRA. This is ok as it is only used for generating the challenge. */
@@ -173,19 +199,19 @@ static BOOL get_md4pw(char *md4pw, char *mach_acct)
  
        if (ret==False) {
                DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
-               pdb_free_sam(sampass);
+               pdb_free_sam(&sampass);
                return False;
        }
 
        if (!(pdb_get_acct_ctrl(sampass) & ACB_DISABLED) && ((pass=pdb_get_nt_passwd(sampass)) != NULL)) {
                memcpy(md4pw, pass, 16);
                dump_data(5, md4pw, 16);
-               pdb_free_sam(sampass);
+               pdb_free_sam(&sampass);
                return True;
        }
        
        DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
-       pdb_free_sam(sampass);
+       pdb_free_sam(&sampass);
        return False;
 
 }
@@ -361,6 +387,16 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
 
        DEBUG(3,("Server Password Set Wksta:[%s]\n", mach_acct));
        
+       /*
+        * Check the machine account name we're changing is the same
+        * as the one we've authenticated from. This prevents arbitrary
+        * machines changing other machine account passwords.
+        */
+
+       if (!strequal(mach_acct, p->dc.mach_acct)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        pdb_init_sam(&sampass);
 
        become_root();
@@ -370,21 +406,9 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
        /* Ensure the account exists and is a machine account. */
 
        if (ret==False || !(pdb_get_acct_ctrl(sampass) & ACB_WSTRUST)) {
-               pdb_free_sam(sampass);
+               pdb_free_sam(&sampass);
                return NT_STATUS_NO_SUCH_USER;
        }
-
-       /*
-        * Check the machine account name we're changing is the same
-        * as the one we've authenticated from. This prevents arbitrary
-        * machines changing other machine account passwords.
-        */
-
-       if (!strequal(mach_acct, p->dc.mach_acct)) {
-               pdb_free_sam(sampass);
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
        
        DEBUG(100,("Server password set : new given value was :\n"));
        for(i = 0; i < 16; i++)
@@ -394,9 +418,27 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
        cred_hash3( pwd, q_u->pwd, p->dc.sess_key, 0);
 
        /* lies!  nt and lm passwords are _not_ the same: don't care */
-       pdb_set_lanman_passwd (sampass, pwd);
-       pdb_set_nt_passwd     (sampass, pwd);
-       pdb_set_acct_ctrl     (sampass, ACB_WSTRUST);
+       if (!pdb_set_lanman_passwd (sampass, pwd)) {
+               pdb_free_sam(&sampass);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (!pdb_set_nt_passwd     (sampass, pwd)) {
+               pdb_free_sam(&sampass);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (!pdb_set_acct_ctrl     (sampass, ACB_WSTRUST)) {
+               pdb_free_sam(&sampass);
+               /* Not quite sure what this one qualifies as, but this will do */
+               return NT_STATUS_NO_MEMORY; 
+       }
+       if (!pdb_set_pass_changed_now     (sampass)) {
+               pdb_free_sam(&sampass);
+               /* Not quite sure what this one qualifies as, but this will do */
+               return NT_STATUS_NO_MEMORY; 
+       }
  
        become_root();
        ret = pdb_update_sam_account (sampass,False);
@@ -408,7 +450,7 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
        /* set up the LSA Server Password Set response */
        init_net_r_srv_pwset(r_u, &srv_cred, status);
 
-       pdb_free_sam(sampass);
+       pdb_free_sam(&sampass);
        return r_u->status;
 }
 
@@ -440,123 +482,6 @@ NTSTATUS _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOF
        return r_u->status;
 }
 
-/*************************************************************************
- _net_logon_any:  Use the new authentications subsystem to log in.
- *************************************************************************/
-
-static NTSTATUS _net_logon_any(NET_ID_INFO_CTR *ctr, char *user, char *domain, char *sess_key)
-{
-       NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
-
-       unsigned char local_lm_response[24];
-       unsigned char local_nt_response[24];
-
-       auth_usersupplied_info user_info;
-       auth_serversupplied_info server_info;
-       AUTH_STR ourdomain, theirdomain, smb_username, wksta_name;
-
-       DEBUG(5, ("_net_logon_any: entered with user %s and domain %s\n", user, domain));
-               
-       ZERO_STRUCT(user_info);
-       ZERO_STRUCT(server_info);
-       ZERO_STRUCT(ourdomain);
-       ZERO_STRUCT(theirdomain);
-       ZERO_STRUCT(smb_username);
-       ZERO_STRUCT(wksta_name);
-       
-       ourdomain.str = lp_workgroup();
-       ourdomain.len = strlen(ourdomain.str);
-
-       theirdomain.str = domain;
-       theirdomain.len = strlen(theirdomain.str);
-
-       user_info.requested_domain = theirdomain;
-       user_info.domain = ourdomain;
-       
-       smb_username.str = user;
-       smb_username.len = strlen(smb_username.str);
-
-       user_info.requested_username = smb_username;  /* For the time-being */
-       user_info.smb_username = smb_username;
-
-#if 0
-       user_info.wksta_name.str = cleint_name();
-       user_info.wksta_name.len = strlen(client_name());
-
-       user_info.wksta_name = wksta_name;
-#endif
-
-       DEBUG(10,("_net_logon_any: Attempting validation level %d.\n", ctr->switch_value));
-       switch (ctr->switch_value) {
-       case NET_LOGON_TYPE:
-               /* Standard challange/response authenticaion */
-
-               user_info.lm_resp.buffer = (uint8 *)ctr->auth.id2.lm_chal_resp.buffer;
-               user_info.lm_resp.len = ctr->auth.id2.lm_chal_resp.str_str_len;
-               user_info.nt_resp.buffer = (uint8 *)ctr->auth.id2.nt_chal_resp.buffer;
-               user_info.nt_resp.len = ctr->auth.id2.nt_chal_resp.str_str_len;
-               memcpy(user_info.chal, ctr->auth.id2.lm_chal, 8);
-               break;
-       case INTERACTIVE_LOGON_TYPE:
-               /* 'Interactive' autheticaion, supplies the password in its MD4 form, encrypted
-                  with the session key.  We will convert this to challange/responce for the 
-                  auth subsystem to chew on */
-       {
-               char nt_pwd[16];
-               char lm_pwd[16];
-               unsigned char key[16];
-               
-               memset(key, 0, 16);
-               memcpy(key, sess_key, 8);
-               
-               memcpy(lm_pwd, ctr->auth.id1.lm_owf.data, 16);
-               memcpy(nt_pwd, ctr->auth.id1.nt_owf.data, 16);
-
-#ifdef DEBUG_PASSWORD
-               DEBUG(100,("key:"));
-               dump_data(100, (char *)key, 16);
-               
-               DEBUG(100,("lm owf password:"));
-               dump_data(100, lm_pwd, 16);
-               
-               DEBUG(100,("nt owf password:"));
-               dump_data(100, nt_pwd, 16);
-#endif
-               
-               SamOEMhash((uchar *)lm_pwd, key, 16);
-               SamOEMhash((uchar *)nt_pwd, key, 16);
-               
-#ifdef DEBUG_PASSWORD
-               DEBUG(100,("decrypt of lm owf password:"));
-               dump_data(100, lm_pwd, 16);
-               
-               DEBUG(100,("decrypt of nt owf password:"));
-               dump_data(100, nt_pwd, 16);
-#endif
-
-               generate_random_buffer(user_info.chal, 8, False);
-               SMBOWFencrypt((const unsigned char *)lm_pwd, user_info.chal, local_lm_response);
-               SMBOWFencrypt((const unsigned char *)nt_pwd, user_info.chal, local_nt_response);
-               user_info.lm_resp.buffer = (uint8 *)local_lm_response;
-               user_info.lm_resp.len = 24;
-               user_info.nt_resp.buffer = (uint8 *)local_nt_response;
-               user_info.nt_resp.len = 24;
-               break;
-       }
-       default:
-               DEBUG(2,("SAM Logon: unsupported switch value\n"));
-               return NT_STATUS_INVALID_INFO_CLASS;
-       } /* end switch */
-       
-       nt_status = check_password(&user_info, &server_info);
-
-       DEBUG(5, ("_net_logon_any: exited with status %s\n", 
-                 get_nt_error_msg(nt_status)));
-
-       return nt_status;
-}
-
-
 
 /*************************************************************************
  _net_sam_logon
@@ -566,14 +491,16 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
 {
        NTSTATUS status = NT_STATUS_OK;
        NET_USER_INFO_3 *usr_info = NULL;
+       NET_ID_INFO_CTR *ctr = q_u->sam_id.ctr;
        DOM_CRED srv_cred;
-       SAM_ACCOUNT *sampass = NULL;
        UNISTR2 *uni_samlogon_user = NULL;
        UNISTR2 *uni_samlogon_domain = NULL;
-       fstring nt_username;
-       fstring nt_domain;
-       BOOL ret;
-
+       UNISTR2 *uni_samlogon_workstation = NULL;
+       fstring nt_username, nt_domain, nt_workstation;
+       auth_usersupplied_info *user_info = NULL;
+       auth_serversupplied_info *server_info = NULL;
+       extern userdom_struct current_user_info;
+               
        usr_info = (NET_USER_INFO_3 *)talloc(p->mem_ctx, sizeof(NET_USER_INFO_3));
        if (!usr_info)
                return NT_STATUS_NO_MEMORY;
@@ -602,14 +529,17 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
     
        switch (q_u->sam_id.logon_level) {
        case INTERACTIVE_LOGON_TYPE:
-               uni_samlogon_user = &q_u->sam_id.ctr->auth.id1.uni_user_name;
-               uni_samlogon_domain = &q_u->sam_id.ctr->auth.id1.uni_domain_name;
+               uni_samlogon_user = &ctr->auth.id1.uni_user_name;
+               uni_samlogon_domain = &ctr->auth.id1.uni_domain_name;
+
+                uni_samlogon_workstation = &ctr->auth.id1.uni_wksta_name;
             
                DEBUG(3,("SAM Logon (Interactive). Domain:[%s].  ", lp_workgroup()));
                break;
        case NET_LOGON_TYPE:
-               uni_samlogon_user = &q_u->sam_id.ctr->auth.id2.uni_user_name;
-               uni_samlogon_domain = &q_u->sam_id.ctr->auth.id2.uni_domain_name;
+               uni_samlogon_user = &ctr->auth.id2.uni_user_name;
+               uni_samlogon_domain = &ctr->auth.id2.uni_domain_name;
+               uni_samlogon_workstation = &ctr->auth.id2.uni_wksta_name;
             
                DEBUG(3,("SAM Logon (Network). Domain:[%s].  ", lp_workgroup()));
                break;
@@ -622,56 +552,109 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
 
        rpcstr_pull(nt_username,uni_samlogon_user->buffer,sizeof(nt_username),uni_samlogon_user->uni_str_len*2,0);
        rpcstr_pull(nt_domain,uni_samlogon_domain->buffer,sizeof(nt_domain),uni_samlogon_domain->uni_str_len*2,0);
+       rpcstr_pull(nt_workstation,uni_samlogon_workstation->buffer,sizeof(nt_workstation),uni_samlogon_workstation->uni_str_len*2,0);
 
-       DEBUG(3,("User:[%s] Requested Domain:[%s]\n", nt_username, nt_domain));
-        
+       DEBUG(3,("User:[%s@%s] Requested Domain:[%s]\n", nt_username, 
+                 nt_workstation, nt_domain));
+       
+       pstrcpy(current_user_info.smb_name, nt_username);
+     
        /*
         * Convert to a UNIX username.
         */
 
-       map_username(nt_username);
+       DEBUG(5,("Attempting validation level %d for unmapped username %s.\n", q_u->sam_id.ctr->switch_value, nt_username));
+
+       switch (ctr->switch_value) {
+       case NET_LOGON_TYPE:
+       {
+               struct auth_context *auth_context = NULL;
+               if (!NT_STATUS_IS_OK(status = make_auth_context_fixed(&auth_context, ctr->auth.id2.lm_chal))) {
+                       return status;
+               }
+
+               /* Standard challenge/response authenticaion */
+               if (!make_user_info_netlogon_network(&user_info, 
+                                                    nt_username, nt_domain, 
+                                                    nt_workstation, 
+                                                    ctr->auth.id2.lm_chal_resp.buffer,
+                                                    ctr->auth.id2.lm_chal_resp.str_str_len,
+                                                    ctr->auth.id2.nt_chal_resp.buffer,
+                                                    ctr->auth.id2.nt_chal_resp.str_str_len)) {
+                       status = NT_STATUS_NO_MEMORY;
+               } else {
+                       status = auth_context->check_ntlm_password(auth_context, user_info, &server_info);
+               }
+               (auth_context->free)(&auth_context);
+                       
+               break;
+       }
+       case INTERACTIVE_LOGON_TYPE:
+               /* 'Interactive' autheticaion, supplies the password in its
+                  MD4 form, encrypted with the session key.  We will
+                  convert this to chellange/responce for the auth
+                  subsystem to chew on */
+       {
+               struct auth_context *auth_context = NULL;
+               const uint8 *chal;
+               if (!NT_STATUS_IS_OK(status = make_auth_context_subsystem(&auth_context))) {
+                       return status;
+               }
+               
+               chal = auth_context->get_ntlm_challenge(auth_context);
+
+               if (!make_user_info_netlogon_interactive(&user_info, 
+                                                        nt_username, nt_domain, 
+                                                        nt_workstation, chal,
+                                                        ctr->auth.id1.lm_owf.data, 
+                                                        ctr->auth.id1.nt_owf.data, 
+                                                        p->dc.sess_key)) {
+                       status = NT_STATUS_NO_MEMORY;
+               } else {
+                       status = auth_context->check_ntlm_password(auth_context, user_info, &server_info);
+               }
 
-       DEBUG(10,("Attempting validation level %d for mapped username %s.\n", q_u->sam_id.ctr->switch_value, nt_username));
+               (auth_context->free)(&auth_context);
 
-       status = _net_logon_any(q_u->sam_id.ctr, nt_username, nt_domain, (char *)p->dc.sess_key);
+               break;
+       }
+       default:
+               DEBUG(2,("SAM Logon: unsupported switch value\n"));
+               return NT_STATUS_INVALID_INFO_CLASS;
+       } /* end switch */
+       
+       free_user_info(&user_info);
+       
+       DEBUG(5, ("_net_sam_logon: check_password returned status %s\n", 
+                 get_nt_error_msg(status)));
 
        /* Check account and password */
     
-       if (NT_STATUS_V(status))
+       if (!NT_STATUS_IS_OK(status)) {
+               free_server_info(&server_info);
                return status;
+       }
 
-       pdb_init_sam(&sampass);
-
-       /* get the account information */
-       become_root();
-       ret = pdb_getsampwnam(sampass, nt_username);
-       unbecome_root();
-
-       if (ret == False){
-               pdb_free_sam(sampass);
-               return NT_STATUS_NO_SUCH_USER;
+       if (server_info->guest) {
+               /* We don't like guest domain logons... */
+               DEBUG(5,("_net_sam_logon: Attempted domain logon as GUEST denied.\n"));
+               free_server_info(&server_info);
+               return NT_STATUS_LOGON_FAILURE;
        }
 
-       /* lkclXXXX this is the point at which, if the login was
-               successful, that the SAM Local Security Authority should
-               record that the user is logged in to the domain.
-       */
+       /* This is the point at which, if the login was successful, that
+           the SAM Local Security Authority should record that the user is
+           logged in to the domain.  */
     
        {
                DOM_GID *gids = NULL;
                int num_gids = 0;
                pstring my_name;
                pstring my_workgroup;
-               pstring domain_groups;
        
                /* set up pointer indicating user/password failed to be found */
                usr_info->ptr_user_info = 0;
         
-               /* XXXX hack to get standard_sub_basic() to use sam logon username */
-               /* possibly a better way would be to do a become_user() call */
-               sam_logon_in_ssb = True;
-               pstrcpy(samlogon_user, nt_username);
-
                pstrcpy(my_workgroup, lp_workgroup());
                pstrcpy(my_name, global_myname);
                strupper(my_name);
@@ -683,29 +666,25 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
                 * rids and then into machine sids for this user.
                 * JRA.
                 */
+
+               gids = NULL;
+               get_domain_user_groups(p->mem_ctx, &num_gids, &gids, server_info->sam_account);
         
-               get_domain_user_groups(domain_groups, nt_username);
-        
-               /*
-                * make_dom_gids allocates the gids array. JRA.
-                */
-               gids = NULL;
-               num_gids = make_dom_gids(p->mem_ctx, domain_groups, &gids);
-        
-               sam_logon_in_ssb = False;
-        
-               init_net_user_info3(p->mem_ctx, usr_info, sampass,
+               init_net_user_info3(p->mem_ctx, usr_info, server_info->sam_account,
                             0, /* logon_count */
                             0, /* bad_pw_count */
                             num_gids,    /* uint32 num_groups */
                             gids    , /* DOM_GID *gids */
                             0x20    , /* uint32 user_flgs (?) */
-                            NULL, /* char sess_key[16] */
+                            NULL, /* uchar sess_key[16] */
                             my_name     , /* char *logon_srv */
                             my_workgroup, /* char *logon_dom */
                             &global_sam_sid,     /* DOM_SID *dom_sid */
                             NULL); /* char *other_sids */
+
        }
-       pdb_free_sam(sampass);
+       free_server_info(&server_info);
        return status;
 }
+
+