Exemplo n.º 1
0
ssize_t   smb_fread(smb_session *s, smb_fd fd, void *buf, size_t buf_size)
{
    smb_file        *file;
    smb_message     *req_msg, resp_msg;
    smb_read_req    req;
    smb_read_resp   *resp;
    size_t          max_read;
    int             res;

    assert(s != NULL && buf != NULL);
    if (!fd)
      return (-1);
    if ((file = smb_session_file_get(s, fd)) == NULL)
        return (-1);

    req_msg = smb_message_new(SMB_CMD_READ);
    if (!req_msg)
        return (-1);
    req_msg->packet->header.tid = file->tid;

    max_read = 0xffff;
    max_read = max_read < buf_size ? max_read : buf_size;

    SMB_MSG_INIT_PKT_ANDX(req);
    req.wct              = 12;
    req.fid              = file->fid;
    req.offset           = file->readp;
    req.max_count        = max_read;
    req.min_count        = max_read;
    req.max_count_high   = 0;
    req.remaining        = 0;
    req.offset_high      = 0;
    req.bct              = 0;
    SMB_MSG_PUT_PKT(req_msg, req);

    res = smb_session_send_msg(s, req_msg);
    smb_message_destroy(req_msg);
    if (!res)
        return (-1);

    if (!smb_session_recv_msg(s, &resp_msg))
        return (-1);
    if (resp_msg.packet->header.status != NT_STATUS_SUCCESS)
        return (-1);

    resp = (smb_read_resp *)resp_msg.packet->payload;
    memcpy(buf, resp->file, resp->data_len);
    smb_fseek(s, fd, resp->data_len, SEEK_CUR);

    return (resp->data_len);
}
Exemplo n.º 2
0
smb_fd      smb_fopen(smb_session *s, smb_tid tid, const char *path,
                      uint32_t o_flags)
{
    smb_share       *share;
    smb_file        *file;
    smb_message     *req_msg, resp_msg;
    smb_create_req req;
    smb_create_resp *resp;
    size_t           path_len;
    int              res;
    char            *utf_path;

    assert(s != NULL && path != NULL);
    if ((share = smb_session_share_get(s, tid)) == NULL)
        return (0);

    path_len = smb_to_utf16(path, strlen(path) + 1, &utf_path);
    if (path_len == 0)
        return (0);

    req_msg = smb_message_new(SMB_CMD_CREATE);
    if (!req_msg) {
        free(utf_path);
        return (0);
    }

    // Set SMB Headers
    req_msg->packet->header.tid = tid;

    // Create AndX Params
    SMB_MSG_INIT_PKT_ANDX(req);
    req.wct            = 24;
    req.flags          = 0;
    req.root_fid       = 0;
    req.access_mask    = o_flags;
    req.alloc_size     = 0;
    req.file_attr      = 0;
    req.share_access   = SMB_SHARE_READ | SMB_SHARE_WRITE;
    req.disposition    = 1;  // 1 = Open and file if doesn't exist
    req.create_opts    = 0;  // We dont't support create
    req.impersonation  = 2;  // ?????
    req.security_flags = 0;  // ???
    req.path_length    = path_len;
    req.bct            = path_len + 1;
    SMB_MSG_PUT_PKT(req_msg, req);

    // Create AndX 'Body'
    smb_message_put8(req_msg, 0);   // Align beginning of path
    smb_message_append(req_msg, utf_path, path_len);
    free(utf_path);

    // smb_message_put16(req_msg, 0);  // ??

    res = smb_session_send_msg(s, req_msg);
    smb_message_destroy(req_msg);
    if (!res)
        return (0);

    if (!smb_session_recv_msg(s, &resp_msg))
        return (0);
    if (resp_msg.packet->header.status != NT_STATUS_SUCCESS)
        return (0);

    resp = (smb_create_resp *)resp_msg.packet->payload;
    file = calloc(1, sizeof(smb_file));
    if (!file)
        return (0);

    file->fid           = resp->fid;
    file->tid           = tid;
    file->created       = resp->created;
    file->accessed      = resp->accessed;
    file->written       = resp->written;
    file->changed       = resp->changed;
    file->alloc_size    = resp->alloc_size;
    file->size          = resp->size;
    file->attr          = resp->attr;
    file->is_dir        = resp->is_dir;

    smb_session_file_add(s, tid, file); // XXX Check return

    return (SMB_FD(tid, file->fid));
}
Exemplo n.º 3
0
static int      auth(smb_session *s, const char *domain, const char *user,
                     const char *password)
{
    smb_message           *msg = NULL, resp;
    smb_session_xsec_req  req;
    smb_buffer            ntlm;
    ASN1_TYPE             token;
    int                   res, der_size = 512;
    char                  der[512], err_desc[ASN1_MAX_ERROR_DESCRIPTION_SIZE];

    msg = smb_message_new(SMB_CMD_SETUP);
    if (!msg)
        return DSM_ERROR_GENERIC;

    // this struct will be set at the end when we know the payload size
    SMB_MSG_ADVANCE_PKT(msg, smb_session_xsec_req);

    asn1_create_element(s->spnego_asn1, "SPNEGO.NegotiationToken", &token);

    // Select a response message type
    res = asn1_write_value(token, "", "negTokenResp", 1);
    if (res != ASN1_SUCCESS) goto error;

    // Delete all optionnal field except 'ResponseToken'
    res = asn1_write_value(token, "negTokenResp.negResult", NULL, 0);
    if (res != ASN1_SUCCESS) goto error;
    res = asn1_write_value(token, "negTokenResp.supportedMech", NULL, 0);
    if (res != ASN1_SUCCESS) goto error;
    res = asn1_write_value(token, "negTokenResp.mechListMIC", NULL, 0);
    if (res != ASN1_SUCCESS) goto error;


    smb_ntlmssp_response(s->srv.challenge, s->srv.ts - 4200, domain, domain, user,
                         password, &s->xsec_target, &ntlm);
    res = asn1_write_value(token, "negTokenResp.responseToken", ntlm.data,
                           ntlm.size);
    smb_buffer_free(&ntlm);
    if (res != ASN1_SUCCESS) goto error;

    res = asn1_der_coding(token, "", der, &der_size, err_desc);
    if (res != ASN1_SUCCESS)
    {
        smb_message_destroy(msg);
        BDSM_dbg("Encoding error: %s", err_desc);
        return DSM_ERROR_GENERIC;
    }

    smb_message_append(msg, der, der_size);
    if (msg->cursor % 2)
        smb_message_put8(msg, 0);
    smb_message_put_utf16(msg, SMB_OS, strlen(SMB_OS));
    smb_message_put16(msg, 0);
    smb_message_put_utf16(msg, SMB_LANMAN, strlen(SMB_LANMAN));
    smb_message_put16(msg, 0);
    smb_message_put16(msg, 0); // Empty PDC name

    SMB_MSG_INIT_PKT_ANDX(req);
    req.wct              = 12;
    req.max_buffer       = SMB_SESSION_MAX_BUFFER;
    req.mpx_count        = 16; // XXX ?
    req.vc_count         = 1;
    req.caps             = s->srv.caps; // XXX caps & our_caps_mask
    req.session_key      = s->srv.session_key;
    req.xsec_blob_size = der_size;
    req.payload_size   = msg->cursor - sizeof(smb_session_xsec_req);
    SMB_MSG_INSERT_PKT(msg, 0, req);

    asn1_delete_structure(&token);

    if (!smb_session_send_msg(s, msg))
    {
        smb_message_destroy(msg);
        BDSM_dbg("Unable to send Session Setup AndX (NTLMSSP_AUTH) message\n");
        return DSM_ERROR_NETWORK;
    }
    smb_message_destroy(msg);

    if (smb_session_recv_msg(s, &resp) == 0)
        return DSM_ERROR_NETWORK;

    if (!smb_session_check_nt_status(s, &resp))
        return DSM_ERROR_NT;
    else
    {
        smb_session_xsec_resp *r = (smb_session_xsec_resp *)resp.packet->payload;
        if (r->action & 0x0001)
            s->guest = true;

        s->srv.uid  = resp.packet->header.uid;
        s->logged = true;

        return DSM_SUCCESS;
    }

error:
    asn1_display_error("smb_session_login auth()", res);
    smb_message_destroy(msg);
    return DSM_ERROR_GENERIC;
}
Exemplo n.º 4
0
static int      negotiate(smb_session *s, const char *domain)
{
    smb_message           *msg = NULL;
    smb_session_xsec_req  req;
    smb_buffer            ntlm;
    ASN1_TYPE             token;
    int                   res, der_size = 128;
    char                  der[128], err_desc[ASN1_MAX_ERROR_DESCRIPTION_SIZE];

    msg = smb_message_new(SMB_CMD_SETUP);
    if (!msg)
        return DSM_ERROR_GENERIC;

    // this struct will be set at the end when we know the payload size
    SMB_MSG_ADVANCE_PKT(msg, smb_session_xsec_req);

    asn1_create_element(s->spnego_asn1, "SPNEGO.GSSAPIContextToken", &token);

    res = asn1_write_value(token, "thisMech", spnego_oid, 1);
    if (res != ASN1_SUCCESS) goto error;
    res = asn1_write_value(token, "spnego", "negTokenInit", 1);
    if (res != ASN1_SUCCESS) goto error;
    res = asn1_write_value(token, "spnego.negTokenInit.mechTypes", "NEW", 1);
    if (res != ASN1_SUCCESS) goto error;
    res = asn1_write_value(token, "spnego.negTokenInit.mechTypes.?1", ntlmssp_oid, 1);
    if (res != ASN1_SUCCESS) goto error;
    res = asn1_write_value(token, "spnego.negTokenInit.reqFlags", NULL, 0);
    if (res != ASN1_SUCCESS) goto error;
    res = asn1_write_value(token, "spnego.negTokenInit.mechListMIC", NULL, 0);
    if (res != ASN1_SUCCESS) goto error;

    smb_ntlmssp_negotiate(domain, domain, &ntlm);
    res = asn1_write_value(token, "spnego.negTokenInit.mechToken", ntlm.data,
                           ntlm.size);
    smb_buffer_free(&ntlm);
    if (res != ASN1_SUCCESS) goto error;

    res = asn1_der_coding(token, "", der, &der_size, err_desc);
    if (res != ASN1_SUCCESS)
    {
        smb_message_destroy(msg);
        BDSM_dbg("Encoding error: %s", err_desc);
        return DSM_ERROR_GENERIC;
    }

    smb_message_append(msg, der, der_size);
    smb_message_put_utf16(msg, SMB_OS, strlen(SMB_OS));
    smb_message_put16(msg, 0);
    smb_message_put_utf16(msg, SMB_LANMAN, strlen(SMB_LANMAN));
    smb_message_put16(msg, 0);
    smb_message_put16(msg, 0);

    SMB_MSG_INIT_PKT_ANDX(req);
    req.wct              = 12;
    req.max_buffer       = SMB_SESSION_MAX_BUFFER;
    req.mpx_count        = 16;
    req.vc_count         = 1;
    req.caps             = s->srv.caps;
    req.session_key      = s->srv.session_key;
    req.xsec_blob_size = der_size;
    req.payload_size   = msg->cursor - sizeof(smb_session_xsec_req);
    SMB_MSG_INSERT_PKT(msg, 0, req);

    asn1_delete_structure(&token);

    if (!smb_session_send_msg(s, msg))
    {
        smb_message_destroy(msg);
        BDSM_dbg("Unable to send Session Setup AndX (NTLMSSP_NEGOTIATE) message\n");
        return DSM_ERROR_NETWORK;
    }

    smb_message_destroy(msg);
    return DSM_SUCCESS;

error:
    asn1_display_error("smb_session_login negotiate()", res);
    smb_message_destroy(msg);
    return DSM_ERROR_GENERIC;
}
Exemplo n.º 5
0
int smb_tree_connect(smb_session *s, const char *name, smb_tid *tid)
{
    smb_tree_connect_req  req;
    smb_tree_connect_resp *resp;
    smb_message            resp_msg;
    smb_message           *req_msg;
    smb_share             *share;
    size_t                 path_len, utf_path_len;
    char                  *path, *utf_path;

    assert(s != NULL && name != NULL && tid != NULL);

    if( s != NULL && name != NULL && tid != NULL ) {

        req_msg = smb_message_new(SMB_CMD_TREE_CONNECT);
        if (!req_msg)
            return DSM_ERROR_GENERIC;

        // Build \\SERVER\Share path from name
        path_len  = strlen(name) + strlen(s->srv.name) + 4;
        path      = alloca(path_len);
        snprintf(path, path_len, "\\\\%s\\%s", s->srv.name, name);
        utf_path_len = smb_to_utf16(path, strlen(path) + 1, &utf_path);

        // Packet headers
        req_msg->packet->header.tid   = 0xffff; // Behavior of libsmbclient

        smb_message_set_andx_members(req_msg);

        // Packet payload
        SMB_MSG_INIT_PKT_ANDX(req);
        req.wct          = 4;
        req.flags        = 0x0c; // (??)
        req.passwd_len   = 1;    // Null byte
        req.bct = utf_path_len + 6 + 1;
        SMB_MSG_PUT_PKT(req_msg, req);

        smb_message_put8(req_msg, 0); // Ze null byte password;
        smb_message_append(req_msg, utf_path, utf_path_len);
        free(utf_path);
        smb_message_append(req_msg, "?????", strlen("?????") + 1);

        if (!smb_session_send_msg(s, req_msg))
        {
            smb_message_destroy(req_msg);
            return DSM_ERROR_NETWORK;
        }
        smb_message_destroy(req_msg);

        if (!smb_session_recv_msg(s, &resp_msg))
            return DSM_ERROR_NETWORK;

        if (!smb_session_check_nt_status(s, &resp_msg))
            return DSM_ERROR_NT;

        resp  = (smb_tree_connect_resp *)resp_msg.packet->payload;
        share = calloc(1, sizeof(smb_share));
        if (!share)
            return DSM_ERROR_GENERIC;

        share->tid          = resp_msg.packet->header.tid;
        share->opts         = resp->opt_support;
        share->rights       = resp->max_rights;
        share->guest_rights = resp->guest_rights;

        smb_session_share_add(s, share);

        *tid = share->tid;
        return 0;
    }

    return DSM_ERROR_GENERIC;
}