s3-net: use new rpccli_spoolss_enumforms wrapper.
[ira/wip.git] / source3 / smbd / sesssetup.c
index 9c9d0a97bca41ad342a4bb0a20a92ffe7ae06c0e..2c29192220b1958d0c47ae1eb51faac6bfb0d147 100644 (file)
 */
 
 #include "includes.h"
+#include "smbd/globals.h"
 
-extern struct auth_context *negprot_global_auth_context;
-extern bool global_encrypted_passwords_negotiated;
-extern bool global_spnego_negotiated;
 extern enum protocol_types Protocol;
-extern int max_send;
-
-uint32 global_client_caps = 0;
 
 /*
   on a logon error possibly map the error to success if "map to guest"
@@ -76,7 +71,7 @@ static int push_signature(uint8 **outbuf)
        if (tmp == -1) return -1;
        result += tmp;
 
-       if (asprintf(&lanman, "Samba %s", SAMBA_VERSION_STRING) != -1) {
+       if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
                tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
                SAFE_FREE(lanman);
        }
@@ -125,21 +120,18 @@ static void reply_sesssetup_blob(struct smb_request *req,
        if (!NT_STATUS_IS_OK(nt_status) &&
            !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
                reply_nterror(req, nt_status_squash(nt_status));
-       } else {
-               nt_status = nt_status_squash(nt_status);
-               SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
-               SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
-               SSVAL(req->outbuf, smb_vwv3, blob.length);
-
-               if ((message_push_blob(&req->outbuf, blob) == -1)
-                   || (push_signature(&req->outbuf) == -1)) {
-                       reply_nterror(req, NT_STATUS_NO_MEMORY);
-               }
+               return;
        }
 
-       show_msg((char *)req->outbuf);
-       srv_send_smb(smbd_server_fd(),(char *)req->outbuf,req->encrypted);
-       TALLOC_FREE(req->outbuf);
+       nt_status = nt_status_squash(nt_status);
+       SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
+       SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
+       SSVAL(req->outbuf, smb_vwv3, blob.length);
+
+       if ((message_push_blob(&req->outbuf, blob) == -1)
+           || (push_signature(&req->outbuf) == -1)) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+       }
 }
 
 /****************************************************************************
@@ -550,11 +542,6 @@ static void reply_spnego_kerberos(struct smb_request *req,
                }
        }
 
-       /* register_existing_vuid keeps the server info */
-       /* register_existing_vuid takes ownership of session_key on success,
-        * no need to free after this on success. A better interface would copy
-        * it.... */
-
        if (!is_partial_auth_vuid(sess_vuid)) {
                sess_vuid = register_initial_vuid();
        }
@@ -563,6 +550,11 @@ static void reply_spnego_kerberos(struct smb_request *req,
        server_info->user_session_key = session_key;
        session_key = data_blob_null;
 
+       /* register_existing_vuid keeps the server info */
+       /* register_existing_vuid takes ownership of session_key on success,
+        * no need to free after this on success. A better interface would copy
+        * it.... */
+
        sess_vuid = register_existing_vuid(sess_vuid,
                                        server_info,
                                        nullblob,
@@ -749,7 +741,7 @@ NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in,
 
        for (i=0;OIDs[i];i++) {
                DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
-               free(OIDs[i]);
+               talloc_free(OIDs[i]);
        }
        return ret;
 }
@@ -803,7 +795,7 @@ static void reply_spnego_negotiate(struct smb_request *req,
 
 #ifdef HAVE_KRB5
        if (kerb_mech && ((lp_security()==SEC_ADS) ||
-                               lp_use_kerberos_keytab()) ) {
+                               USE_KERBEROS_KEYTAB) ) {
                bool destroy_vuid = True;
                reply_spnego_kerberos(req, &secblob, kerb_mech,
                                      vuid, &destroy_vuid);
@@ -895,7 +887,7 @@ static void reply_spnego_auth(struct smb_request *req,
                                (unsigned long)secblob.length));
 #ifdef HAVE_KRB5
                if (kerb_mech && ((lp_security()==SEC_ADS) ||
-                                       lp_use_kerberos_keytab()) ) {
+                                       USE_KERBEROS_KEYTAB)) {
                        bool destroy_vuid = True;
                        reply_spnego_kerberos(req, &secblob, kerb_mech,
                                              vuid, &destroy_vuid);
@@ -918,7 +910,7 @@ static void reply_spnego_auth(struct smb_request *req,
                        DEBUG(3,("reply_spnego_auth: network "
                                "misconfiguration, client sent us a "
                                "krb5 ticket and kerberos security "
-                               "not enabled"));
+                               "not enabled\n"));
                        reply_nterror(req, nt_status_squash(
                                        NT_STATUS_LOGON_FAILURE));
                        SAFE_FREE(kerb_mech);
@@ -955,12 +947,6 @@ static void reply_spnego_auth(struct smb_request *req,
        return;
 }
 
-/****************************************************************************
- List to store partial SPNEGO auth fragments.
-****************************************************************************/
-
-static struct pending_auth_data *pd_list;
-
 /****************************************************************************
  Delete an entry on the list.
 ****************************************************************************/
@@ -1001,7 +987,7 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
                DATA_BLOB *pblob)
 {
        struct pending_auth_data *pad = NULL;
-       ASN1_DATA data;
+       ASN1_DATA *data;
        size_t needed_len = 0;
 
        pad = get_pending_auth_data(smbpid);
@@ -1088,34 +1074,39 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
         * the data given in this blob is enough.
         */
 
-       asn1_load(&data, *pblob);
-       asn1_start_tag(&data, pblob->data[0]);
-       if (data.has_error || data.nesting == NULL) {
-               asn1_free(&data);
+       data = asn1_init(NULL);
+       if (data == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       asn1_load(data, *pblob);
+       asn1_start_tag(data, pblob->data[0]);
+       if (data->has_error || data->nesting == NULL) {
+               asn1_free(data);
                /* Let caller catch. */
                return NT_STATUS_OK;
        }
 
        /* Integer wrap paranoia.... */
 
-       if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
-           data.nesting->taglen + data.nesting->start < data.nesting->start) {
+       if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
+           data->nesting->taglen + data->nesting->start < data->nesting->start) {
 
                DEBUG(2,("check_spnego_blob_complete: integer wrap "
                        "data.nesting->taglen = %u, "
                        "data.nesting->start = %u\n",
-                       (unsigned int)data.nesting->taglen,
-                       (unsigned int)data.nesting->start ));
+                       (unsigned int)data->nesting->taglen,
+                       (unsigned int)data->nesting->start ));
 
-               asn1_free(&data);
+               asn1_free(data);
                return NT_STATUS_INVALID_PARAMETER;
        }
 
        /* Total length of the needed asn1 is the tag length
         * plus the current offset. */
 
-       needed_len = data.nesting->taglen + data.nesting->start;
-       asn1_free(&data);
+       needed_len = data->nesting->taglen + data->nesting->start;
+       asn1_free(data);
 
        DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
                "pblob->length = %u\n",
@@ -1159,23 +1150,25 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
 
 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
 {
-       uint8 *p;
+       const uint8 *p;
        DATA_BLOB blob1;
        size_t bufrem;
-       fstring native_os, native_lanman, primary_domain;
+       char *tmp;
+       const char *native_os;
+       const char *native_lanman;
+       const char *primary_domain;
        const char *p2;
-       uint16 data_blob_len = SVAL(req->inbuf, smb_vwv7);
+       uint16 data_blob_len = SVAL(req->vwv+7, 0);
        enum remote_arch_types ra_type = get_remote_arch();
-       int vuid = SVAL(req->inbuf,smb_uid);
+       int vuid = req->vuid;
        user_struct *vuser = NULL;
        NTSTATUS status = NT_STATUS_OK;
        uint16 smbpid = req->smbpid;
-       uint16 smb_flag2 = req->flags2;
 
        DEBUG(3,("Doing spnego session setup\n"));
 
        if (global_client_caps == 0) {
-               global_client_caps = IVAL(req->inbuf,smb_vwv10);
+               global_client_caps = IVAL(req->vwv+10, 0);
 
                if (!(global_client_caps & CAP_STATUS32)) {
                        remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
@@ -1183,7 +1176,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
 
        }
 
-       p = (uint8 *)smb_buf(req->inbuf);
+       p = req->buf;
 
        if (data_blob_len == 0) {
                /* an invalid request */
@@ -1191,7 +1184,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
                return;
        }
 
-       bufrem = smb_bufrem(req->inbuf, p);
+       bufrem = smbreq_bufrem(req, p);
        /* pull the spnego blob */
        blob1 = data_blob(p, MIN(bufrem, data_blob_len));
 
@@ -1199,13 +1192,20 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
        file_save("negotiate.dat", blob1.data, blob1.length);
 #endif
 
-       p2 = (char *)req->inbuf + smb_vwv13 + data_blob_len;
-       p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_os, p2,
-                             sizeof(native_os), STR_TERMINATE);
-       p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_lanman, p2,
-                             sizeof(native_lanman), STR_TERMINATE);
-       p2 += srvstr_pull_buf(req->inbuf, smb_flag2, primary_domain, p2,
-                             sizeof(primary_domain), STR_TERMINATE);
+       p2 = (char *)req->buf + data_blob_len;
+
+       p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
+                                    STR_TERMINATE);
+       native_os = tmp ? tmp : "";
+
+       p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
+                                    STR_TERMINATE);
+       native_lanman = tmp ? tmp : "";
+
+       p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
+                                    STR_TERMINATE);
+       primary_domain = tmp ? tmp : "";
+
        DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
                native_os, native_lanman, primary_domain));
 
@@ -1352,8 +1352,8 @@ static int shutdown_other_smbds(struct db_record *rec,
                return 0;
        }
 
-       DEBUG(0,("shutdown_other_smbds: shutting down pid %d "
-                "(IP %s)\n", procid_to_pid(&crec->pid), ip));
+       DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
+                "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid), ip));
 
        messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
                       &data_blob_null);
@@ -1388,13 +1388,13 @@ void reply_sesssetup_and_X(struct smb_request *req)
        DATA_BLOB lm_resp;
        DATA_BLOB nt_resp;
        DATA_BLOB plaintext_password;
-       fstring user;
+       char *tmp;
+       const char *user;
        fstring sub_user; /* Sainitised username for substituion */
-       fstring domain;
-       fstring native_os;
-       fstring native_lanman;
-       fstring primary_domain;
-       static bool done_sesssetup = False;
+       const char *domain;
+       const char *native_os;
+       const char *native_lanman;
+       const char *primary_domain;
        auth_usersupplied_info *user_info = NULL;
        auth_serversupplied_info *server_info = NULL;
        uint16 smb_flag2 = req->flags2;
@@ -1426,7 +1426,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
                        return;
                }
 
-               if (SVAL(req->inbuf,smb_vwv4) == 0) {
+               if (SVAL(req->vwv+4, 0) == 0) {
                        setup_new_vc_session();
                }
 
@@ -1435,18 +1435,16 @@ void reply_sesssetup_and_X(struct smb_request *req)
                return;
        }
 
-       smb_bufsize = SVAL(req->inbuf,smb_vwv2);
+       smb_bufsize = SVAL(req->vwv+2, 0);
 
        if (Protocol < PROTOCOL_NT1) {
-               uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
+               uint16 passlen1 = SVAL(req->vwv+7, 0);
 
                /* Never do NT status codes with protocols before NT1 as we
                 * don't get client caps. */
                remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
 
-               if ((passlen1 > MAX_PASS_LEN)
-                   || (passlen1 > smb_bufrem(req->inbuf,
-                                             smb_buf(req->inbuf)))) {
+               if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
                        reply_nterror(req, nt_status_squash(
                                              NT_STATUS_INVALID_PARAMETER));
                        END_PROFILE(SMBsesssetupX);
@@ -1454,30 +1452,30 @@ void reply_sesssetup_and_X(struct smb_request *req)
                }
 
                if (doencrypt) {
-                       lm_resp = data_blob(smb_buf(req->inbuf), passlen1);
+                       lm_resp = data_blob(req->buf, passlen1);
                } else {
-                       plaintext_password = data_blob(smb_buf(req->inbuf),
-                                                      passlen1+1);
+                       plaintext_password = data_blob(req->buf, passlen1+1);
                        /* Ensure null termination */
                        plaintext_password.data[passlen1] = 0;
                }
 
-               srvstr_pull_buf(req->inbuf, req->flags2, user,
-                               smb_buf(req->inbuf)+passlen1, sizeof(user),
-                               STR_TERMINATE);
-               *domain = 0;
+               srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
+                                      req->buf + passlen1, STR_TERMINATE);
+               user = tmp ? tmp : "";
+
+               domain = "";
 
        } else {
-               uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
-               uint16 passlen2 = SVAL(req->inbuf,smb_vwv8);
+               uint16 passlen1 = SVAL(req->vwv+7, 0);
+               uint16 passlen2 = SVAL(req->vwv+8, 0);
                enum remote_arch_types ra_type = get_remote_arch();
-               char *p = smb_buf(req->inbuf);
-               char *save_p = smb_buf(req->inbuf);
+               const uint8_t *p = req->buf;
+               const uint8_t *save_p = req->buf;
                uint16 byte_count;
 
 
                if(global_client_caps == 0) {
-                       global_client_caps = IVAL(req->inbuf,smb_vwv11);
+                       global_client_caps = IVAL(req->vwv+11, 0);
 
                        if (!(global_client_caps & CAP_STATUS32)) {
                                remove_from_common_flags2(
@@ -1519,7 +1517,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
 
                /* check for nasty tricks */
                if (passlen1 > MAX_PASS_LEN
-                   || passlen1 > smb_bufrem(req->inbuf, p)) {
+                   || passlen1 > smbreq_bufrem(req, p)) {
                        reply_nterror(req, nt_status_squash(
                                              NT_STATUS_INVALID_PARAMETER));
                        END_PROFILE(SMBsesssetupX);
@@ -1527,7 +1525,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
                }
 
                if (passlen2 > MAX_PASS_LEN
-                   || passlen2 > smb_bufrem(req->inbuf, p+passlen1)) {
+                   || passlen2 > smbreq_bufrem(req, p+passlen1)) {
                        reply_nterror(req, nt_status_squash(
                                              NT_STATUS_INVALID_PARAMETER));
                        END_PROFILE(SMBsesssetupX);
@@ -1557,7 +1555,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
                                                        req->inbuf,
                                                        req->flags2,
                                                        &pass,
-                                                       smb_buf(req->inbuf),
+                                                       req->buf,
                                                        passlen1,
                                                        STR_TERMINATE|STR_ASCII);
                        } else {
@@ -1565,7 +1563,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
                                                        req->inbuf,
                                                        req->flags2,
                                                        &pass,
-                                                       smb_buf(req->inbuf),
+                                                       req->buf,
                                                        unic ? passlen2 : passlen1,
                                                        STR_TERMINATE);
                        }
@@ -1579,15 +1577,22 @@ void reply_sesssetup_and_X(struct smb_request *req)
                }
 
                p += passlen1 + passlen2;
-               p += srvstr_pull_buf(req->inbuf, req->flags2, user, p,
-                                    sizeof(user), STR_TERMINATE);
-               p += srvstr_pull_buf(req->inbuf, req->flags2, domain, p,
-                                    sizeof(domain), STR_TERMINATE);
-               p += srvstr_pull_buf(req->inbuf, req->flags2, native_os,
-                                    p, sizeof(native_os), STR_TERMINATE);
-               p += srvstr_pull_buf(req->inbuf, req->flags2,
-                                    native_lanman, p, sizeof(native_lanman),
-                                    STR_TERMINATE);
+
+               p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
+                                           STR_TERMINATE);
+               user = tmp ? tmp : "";
+
+               p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
+                                           STR_TERMINATE);
+               domain = tmp ? tmp : "";
+
+               p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
+                                           STR_TERMINATE);
+               native_os = tmp ? tmp : "";
+
+               p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
+                                           STR_TERMINATE);
+               native_lanman = tmp ? tmp : "";
 
                /* not documented or decoded by Ethereal but there is one more
                 * string in the extra bytes which is the same as the
@@ -1596,14 +1601,13 @@ void reply_sesssetup_and_X(struct smb_request *req)
                 * Windows 9x does not include a string here at all so we have
                 * to check if we have any extra bytes left */
 
-               byte_count = SVAL(req->inbuf, smb_vwv13);
+               byte_count = SVAL(req->vwv+13, 0);
                if ( PTR_DIFF(p, save_p) < byte_count) {
-                       p += srvstr_pull_buf(req->inbuf, req->flags2,
-                                            primary_domain, p,
-                                            sizeof(primary_domain),
-                                            STR_TERMINATE);
+                       p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
+                                                   STR_TERMINATE);
+                       primary_domain = tmp ? tmp : "";
                } else {
-                       fstrcpy( primary_domain, "null" );
+                       primary_domain = talloc_strdup(talloc_tos(), "null");
                }
 
                DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] "
@@ -1619,7 +1623,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
 
        }
 
-       if (SVAL(req->inbuf,smb_vwv4) == 0) {
+       if (SVAL(req->vwv+4, 0) == 0) {
                setup_new_vc_session();
        }
 
@@ -1660,7 +1664,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
                add_session_user(sub_user);
                add_session_workgroup(domain);
                /* Then force it to null for the benfit of the code below */
-               *user = 0;
+               user = "";
        }
 
        if (!*user) {
@@ -1687,14 +1691,15 @@ void reply_sesssetup_and_X(struct smb_request *req)
                }
        } else {
                struct auth_context *plaintext_auth_context = NULL;
-               const uint8 *chal;
 
                nt_status = make_auth_context_subsystem(
                                &plaintext_auth_context);
 
                if (NT_STATUS_IS_OK(nt_status)) {
-                       chal = plaintext_auth_context->get_ntlm_challenge(
-                                       plaintext_auth_context);
+                       uint8_t chal[8];
+
+                       plaintext_auth_context->get_ntlm_challenge(
+                                       plaintext_auth_context, chal);
 
                        if (!make_user_info_for_reply(&user_info,
                                                      user, domain, chal,