Exemple #1
0
void        smb_ntlm2_hash(const char *user, const char *password,
                           const char *dest, smb_ntlmh *hash)
{
    smb_ntlmh     hash_v1;
    char          *ucs_user, *ucs_dest, *data, user_upper[64];
    size_t        ucs_user_len, ucs_dest_len, data_len;

    smb_ntlm_hash(password, &hash_v1);

    strlcpy(user_upper, user, 64);
    _upcase(user_upper);

    ucs_user_len  = smb_to_utf16(user_upper, strlen(user_upper), &ucs_user);
    ucs_dest_len  = smb_to_utf16(dest, strlen(dest), &ucs_dest);
    data_len      = ucs_user_len + ucs_dest_len;
    data          = alloca(data_len);

    memcpy(data, ucs_user, ucs_user_len);
    memcpy(data + ucs_user_len, ucs_dest, ucs_dest_len);

    HMAC_MD5(hash_v1, SMB_NTLM_HASH_SIZE, data, data_len, hash);

    free(ucs_user);
    free(ucs_dest);
}
Exemple #2
0
void        smb_ntlm_hash(const char *password, smb_ntlmh *hash)
{
    MD4_CTX   ctx;
    char      *ucs2le_pass;
    size_t    sz;

    assert(password != NULL && hash != NULL);

    sz = smb_to_utf16(password, strlen(password), &ucs2le_pass);
    memset((void *)hash, 0, SMB_NTLM_HASH_SIZE);

    MD4_Init(&ctx);
    MD4_Update(&ctx, (uint8_t *)ucs2le_pass, sz);
    MD4_Final((uint8_t *)hash, &ctx);

    free(ucs2le_pass);
}
Exemple #3
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));
}
Exemple #4
0
void        smb_ntlmssp_response(uint64_t srv_challenge, uint64_t srv_ts,
                                 const char *host, const char *domain,
                                 const char *user, const char *password,
                                 smb_buffer *target, smb_buffer *token)
{
    smb_ntlmssp_auth      *auth;
    smb_ntlm_blob         *blob;
    smb_ntlmh             hash_v2, xkey, xkey_crypt;
    smb_buffer            buf;
    void                  *lm2, *ntlm2;
    size_t                blob_size, utf_sz, cursor = 0;
    uint64_t              user_challenge;
    char                  *utf;

    assert(host != NULL && domain != NULL && user != NULL && password != NULL);
    assert(token != NULL && target != NULL);

    //// We compute most of the data first to know the final token size
    smb_ntlm2_hash(user, password, domain, &hash_v2);
    user_challenge = smb_ntlm_generate_challenge();
    smb_ntlm_generate_xkey(&xkey);
    blob_size = smb_ntlm_make_blob(&blob, srv_ts, user_challenge, target);

    lm2   = smb_lm2_response(&hash_v2, srv_challenge, smb_ntlm_generate_challenge());
    smb_buffer_init(&buf, blob, blob_size);
    ntlm2 = smb_ntlm2_response(&hash_v2, srv_challenge, &buf);
    smb_ntlm2_session_key(&hash_v2, ntlm2, &xkey, &xkey_crypt);

    smb_buffer_init(&buf, NULL, 0);
    free(blob);

    // Compute size of and allocate token
    token->size = sizeof(smb_ntlmssp_auth)
                  + strlen(host) * 2
                  + strlen(domain) * 2
                  + strlen(user) * 2
                  + blob_size + 16 // Blob + HMAC
                  + 8 + 16  // LM2 Response (miniblob=user_challenge + HMAC)
                  + 16;     // Session Key
    if (token->size % 2) // Align on Word
        token->size += 1;
    smb_buffer_alloc(token, token->size);

    auth = (smb_ntlmssp_auth *)token->data;
    memset(auth, 0, token->size);

    memcpy(auth->id, "NTLMSSP", 8);
    auth->type  = SMB_NTLMSSP_CMD_AUTH;
    auth->flags = 0x60088215;


    __AUTH_APPEND(lm, lm2, 24, cursor)
    __AUTH_APPEND(ntlm, ntlm2, blob_size + 16, cursor)

    utf_sz = smb_to_utf16(domain, strlen(domain), &utf);
    __AUTH_APPEND(domain, utf, utf_sz, cursor)
    free(utf);
    utf_sz = smb_to_utf16(user, strlen(user), &utf);
    __AUTH_APPEND(user, utf, utf_sz, cursor)
    free(utf);
    utf_sz = smb_to_utf16(host, strlen(host), &utf);
    __AUTH_APPEND(host, utf, utf_sz, cursor)
    free(utf);

    __AUTH_APPEND(session_key, &xkey_crypt, 16, cursor)

    free(lm2);
    free(ntlm2);
}
Exemple #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;
}
Exemple #6
0
smb_file  *smb_fstat(smb_session *s, smb_tid tid, const char *path)
{
    smb_message           *msg, reply;
    smb_trans2_req        tr2;
    smb_trans2_resp       *tr2_resp;
    smb_tr2_query         query;
    smb_tr2_path_info     *info;
    smb_file              *file;
    size_t                utf_path_len, msg_len;
    char                  *utf_path;
    int                   res, padding = 0;

    assert(s != NULL && path != NULL);

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

    msg_len   = sizeof(smb_trans2_req) + sizeof(smb_tr2_query);
    msg_len  += utf_path_len;
    if (msg_len %4)
        padding = 4 - msg_len % 4;

    msg = smb_message_new(SMB_CMD_TRANS2);
    if (!msg) {
        free(utf_path);
        return 0;
    }
    msg->packet->header.tid = tid;

    SMB_MSG_INIT_PKT(tr2);
    tr2.wct                = 15;
    tr2.total_param_count  = utf_path_len + sizeof(smb_tr2_query);
    tr2.param_count        = tr2.total_param_count;
    tr2.max_param_count    = 2; // ?? Why not the same or 12 ?
    tr2.max_data_count     = 0xffff;
    tr2.param_offset       = 68; // Offset of find_first_params in packet;
    tr2.data_count         = 0;
    tr2.data_offset        = 96; // Offset of pattern in packet
    tr2.setup_count        = 1;
    tr2.cmd                = SMB_TR2_QUERY_PATH;
    tr2.bct                = sizeof(smb_tr2_query) + utf_path_len + padding;
    SMB_MSG_PUT_PKT(msg, tr2);

    SMB_MSG_INIT_PKT(query);
    query.interest   = SMB_FIND2_QUERY_FILE_ALL_INFO;
    SMB_MSG_PUT_PKT(msg, query);

    smb_message_append(msg, utf_path, utf_path_len);
    free(utf_path);

    // Adds padding at the end if necessary.
    while (padding--)
        smb_message_put8(msg, 0);

    res = smb_session_send_msg(s, msg);
    smb_message_destroy(msg);
    if (!res)
    {
        BDSM_dbg("Unable to query pattern: %s\n", path);
        return NULL;
    }

    if (!smb_session_recv_msg(s, &reply)
        || reply.packet->header.status != NT_STATUS_SUCCESS)
    {
        BDSM_dbg("Unable to recv msg or failure for %s\n", path);
        return NULL;
    }

    tr2_resp  = (smb_trans2_resp *)reply.packet->payload;
    info      = (smb_tr2_path_info *)(tr2_resp->payload + 4); //+4 is padding
    file      = calloc(1, sizeof(smb_file));
    if (!file)
        return NULL;

    file->name_len  = smb_from_utf16((const char *)info->name, info->name_len,
                                     &file->name);
    file->name[info->name_len / 2] = 0;

    file->created     = info->created;
    file->accessed    = info->accessed;
    file->written     = info->written;
    file->changed     = info->changed;
    file->alloc_size  = info->alloc_size;
    file->size        = info->size;
    file->attr        = info->attr;
    file->is_dir      = info->is_dir;

    return file;
}
Exemple #7
0
static smb_message  *smb_trans2_find_next (smb_session *s, smb_tid tid, uint16_t resume_key, uint16_t sid, const char *pattern)
{
    smb_message           *msg_find_next2 = NULL;
    smb_trans2_req        tr2_find_next2;
    smb_tr2_findnext2     find_next2;
    size_t                utf_pattern_len, tr2_bct, tr2_param_count;
    char                  *utf_pattern;
    int                   res;
    unsigned int          padding = 0;

    assert(s != NULL && pattern != NULL);

    utf_pattern_len = smb_to_utf16(pattern, strlen(pattern) + 1, &utf_pattern);
    if (utf_pattern_len == 0)
        return NULL;

    tr2_bct = sizeof(smb_tr2_findnext2) + utf_pattern_len;
    tr2_param_count = tr2_bct;
    tr2_bct += 3;
    // Adds padding at the end if necessary.
    while ((tr2_bct % 4) != 3)
    {
        padding++;
        tr2_bct++;
    }

    msg_find_next2 = smb_message_new(SMB_CMD_TRANS2);
    if (!msg_find_next2)
    {
        free(utf_pattern);
        return NULL;
    }
    msg_find_next2->packet->header.tid = tid;

    SMB_MSG_INIT_PKT(tr2_find_next2);
    tr2_find_next2.wct                = 0x0f;
    tr2_find_next2.total_param_count  = tr2_param_count;
    tr2_find_next2.total_data_count   = 0x0000;
    tr2_find_next2.max_param_count    = 10; // ?? Why not the same or 12 ?
    tr2_find_next2.max_data_count     = 0xffff;
    //max_setup_count
    //reserved
    //flags
    //timeout
    //reserve2
    tr2_find_next2.param_count        = tr2_param_count;
    tr2_find_next2.param_offset       = 68; // Offset of find_next_params in packet;
    tr2_find_next2.data_count         = 0;
    tr2_find_next2.data_offset        = 88; // Offset of pattern in packet
    tr2_find_next2.setup_count        = 1;
    //reserve3
    tr2_find_next2.cmd                = SMB_TR2_FIND_NEXT;
    tr2_find_next2.bct = tr2_bct; //3 == padding
    SMB_MSG_PUT_PKT(msg_find_next2, tr2_find_next2);

    SMB_MSG_INIT_PKT(find_next2);
    find_next2.sid        = sid;
    find_next2.count      = 255;
    find_next2.interest   = SMB_FIND2_INTEREST_BOTH_DIRECTORY_INFO;
    find_next2.flags      = SMB_FIND2_FLAG_CLOSE_EOS|SMB_FIND2_FLAG_CONTINUE;
    find_next2.resume_key = resume_key;
    SMB_MSG_PUT_PKT(msg_find_next2, find_next2);
    smb_message_append(msg_find_next2, utf_pattern, utf_pattern_len);
    while (padding--)
        smb_message_put8(msg_find_next2, 0);

    res = smb_session_send_msg(s, msg_find_next2);
    smb_message_destroy(msg_find_next2);
    free(utf_pattern);

    if (!res)
    {
        BDSM_dbg("Unable to query pattern: %s\n", pattern);
        return NULL;
    }

    msg_find_next2 = smb_tr2_recv(s);
    return msg_find_next2;
}
Exemple #8
0
static smb_message  *smb_trans2_find_first (smb_session *s, smb_tid tid, const char *pattern)
{
    smb_message           *msg;
    smb_trans2_req        tr2;
    smb_tr2_findfirst2    find;
    size_t                utf_pattern_len, tr2_bct, tr2_param_count;
    char                  *utf_pattern;
    int                   res;
    unsigned int          padding = 0;

    assert(s != NULL && pattern != NULL);

    utf_pattern_len = smb_to_utf16(pattern, strlen(pattern) + 1, &utf_pattern);
    if (utf_pattern_len == 0)
        return NULL;

    tr2_bct = sizeof(smb_tr2_findfirst2) + utf_pattern_len;
    tr2_param_count = tr2_bct;
    tr2_bct += 3;
    // Adds padding at the end if necessary.
    while ((tr2_bct % 4) != 3)
    {
        padding++;
        tr2_bct++;
    }

    msg = smb_message_new(SMB_CMD_TRANS2);
    if (!msg) {
        free(utf_pattern);
        return NULL;
    }
    msg->packet->header.tid = tid;

    SMB_MSG_INIT_PKT(tr2);
    tr2.wct                = 15;
    tr2.max_param_count    = 10; // ?? Why not the same or 12 ?
    tr2.max_data_count     = 0xffff;;
    tr2.param_offset       = 68; // Offset of find_first_params in packet;
    tr2.data_count         = 0;
    tr2.data_offset        = 88; // Offset of pattern in packet
    tr2.setup_count        = 1;
    tr2.cmd                = SMB_TR2_FIND_FIRST;
    tr2.total_param_count = tr2_param_count;
    tr2.param_count       = tr2_param_count;
    tr2.bct = tr2_bct; //3 == padding
    SMB_MSG_PUT_PKT(msg, tr2);

    SMB_MSG_INIT_PKT(find);
    find.attrs     = SMB_FIND2_ATTR_DEFAULT;
    find.count     = 1366;     // ??
    find.flags     = SMB_FIND2_FLAG_CLOSE_EOS | SMB_FIND2_FLAG_RESUME;
    find.interest  = SMB_FIND2_INTEREST_BOTH_DIRECTORY_INFO;
    SMB_MSG_PUT_PKT(msg, find);
    smb_message_append(msg, utf_pattern, utf_pattern_len);
    while (padding--)
        smb_message_put8(msg, 0);

    res = smb_session_send_msg(s, msg);
    smb_message_destroy(msg);
    free(utf_pattern);

    if (!res)
    {
        BDSM_dbg("Unable to query pattern: %s\n", pattern);
        return NULL;
    }

    msg = smb_tr2_recv(s);
    return msg;
}