static int smb_connect( stream_t *p_access, const char *psz_login, const char *psz_password, const char *psz_domain) { access_sys_t *p_sys = p_access->p_sys; smb_session_set_creds( p_sys->p_session, psz_domain, psz_login, psz_password ); if( smb_session_login( p_sys->p_session ) == DSM_SUCCESS ) { if( p_sys->psz_share ) { /* Connect to the share */ if( smb_tree_connect( p_sys->p_session, p_sys->psz_share, &p_sys->i_tid ) != DSM_SUCCESS ) return VLC_EGENERIC; /* Let's finally ask a handle to the file we wanna read ! */ return smb_fopen( p_sys->p_session, p_sys->i_tid, p_sys->psz_path, SMB_MOD_RO, &p_sys->i_fd ) == DSM_SUCCESS ? VLC_SUCCESS : VLC_EGENERIC; } else return VLC_SUCCESS; } else return VLC_EGENERIC; }
int main() { struct in_addr addr; smb_session *session; smb_tid tid; smb_fd fd; session = smb_session_new(); if (session == NULL) exit(1); inet_aton("127.0.0.1", &addr.sin_addr); if (smb_session_connect(session, "MYNAME", addr.sin_addr.s_addr, SMB_TRANSPORT_TCP)) { printf("Unable to connect to host\n"); exit(2); } smb_session_set_creds(session, "MYNAME", "login", "password"); if (smb_session_login(session)) { if (session->guest) printf("Logged in as GUEST \n"); else printf("Successfully logged in\n"); } else { printf("Auth failed\n"); exit(3); } tid = smb_tree_connect(session, "MyShare"); if (!tid) { printf("Unable to connect to share\n"); exit(4); } fd = smb_fopen(session, tid, "\\My\\File"); if (!fd) { printf("Unable to open file\n"); exit(5); } char buffer[512]; smb_fread(session, fd, buffer, 512); /* Use data */ smb_fclose(session, fd); smb_tree_disconnect(session, tid); smb_session_destroy(session); return(0); }
static int smb_connect( access_t *p_access, const char *psz_login, const char *psz_password, const char *psz_domain ) { access_sys_t *p_sys = p_access->p_sys; smb_session_set_creds( p_sys->p_session, psz_domain, psz_login, psz_password ); if( smb_session_login( p_sys->p_session ) ) { if( p_sys->psz_share ) { /* Connect to the share */ p_sys->i_tid = smb_tree_connect( p_sys->p_session, p_sys->psz_share ); if( !p_sys->i_tid ) return VLC_EGENERIC; /* Let's finally ask a handle to the file we wanna read ! */ p_sys->i_fd = smb_fopen( p_sys->p_session, p_sys->i_tid, p_sys->psz_path, SMB_MOD_RO ); /* TODO: fix smb_fopen to return a specific error code in case of * wrong permissions */ return p_sys->i_fd > 0 ? VLC_SUCCESS : VLC_EGENERIC; } else return VLC_SUCCESS; } else return VLC_EGENERIC; }
static int smb_connect( access_t *p_access ) { access_sys_t *p_sys = p_access->p_sys; const char *psz_login = p_sys->creds.login ? p_sys->creds.login : "******"; const char *psz_password = p_sys->creds.password ? p_sys->creds.password : "******"; const char *psz_domain = p_sys->creds.domain ? p_sys->creds.domain : p_sys->netbios_name; smb_session_set_creds( p_sys->p_session, psz_domain, psz_login, psz_password ); if( smb_session_login( p_sys->p_session ) ) { if( p_sys->psz_share ) { /* Connect to the share */ p_sys->i_tid = smb_tree_connect( p_sys->p_session, p_sys->psz_share ); if( !p_sys->i_tid ) return VLC_EGENERIC; } return VLC_SUCCESS; } else return VLC_EGENERIC; }
static int ejs_cli_tree_connect(MprVarHandle eid, int argc, MprVar **argv) { struct smbcli_session *session; struct smbcli_tree *tree; union smb_tcon tcon; TALLOC_CTX *mem_ctx; NTSTATUS status; const char *password = ""; /* Argument parsing */ if (argc != 2) { ejsSetErrorMsg(eid, "tree_connect invalid arguments"); return -1; } if (!mprVarIsPtr(argv[0]->type)) { ejsSetErrorMsg(eid, "first arg is not a session handle"); return -1; } session = argv[0]->ptr; tree = smbcli_tree_init(session, session, False); if (!tree) { ejsSetErrorMsg(eid, "tree init failed"); return -1; } mem_ctx = talloc_init("tcon"); if (!mem_ctx) { ejsSetErrorMsg(eid, "talloc_init failed"); return -1; } /* Do tree connect */ tcon.generic.level = RAW_TCON_TCONX; tcon.tconx.in.flags = 0; if (session->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) { tcon.tconx.in.password = data_blob(NULL, 0); } else if (session->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) { tcon.tconx.in.password = data_blob_talloc(mem_ctx, NULL, 24); if (session->transport->negotiate.secblob.length < 8) { ejsSetErrorMsg(eid, "invalid security blob"); return -1; } SMBencrypt(password, session->transport->negotiate.secblob.data, tcon.tconx.in.password.data); } else { tcon.tconx.in.password = data_blob_talloc(mem_ctx, password, strlen(password)+1); } tcon.tconx.in.path = argv[1]->string; tcon.tconx.in.device = "?????"; status = smb_tree_connect(tree, mem_ctx, &tcon); if (!NT_STATUS_IS_OK(status)) { ejsSetErrorMsg(eid, "tree_connect: %s", nt_errstr(status)); return -1; } tree->tid = tcon.tconx.out.tid; talloc_free(mem_ctx); mpr_Return(eid, mprCreatePtrVar(tree)); return 0; }
// We should normally implement SCERPC and SRVSVC to perform a share list. But // since these two protocols have no other use for us, we'll do it the trash way // PS: Worst function _EVER_. I don't understand a bit myself int smb_share_get_list(smb_session *s, smb_share_list *list, size_t *pcount) { smb_message *req, resp; smb_trans_req trans; smb_tid ipc_tid; smb_fd srvscv_fd; uint16_t rpc_len; size_t res, frag_len_cursor; ssize_t count; int ret; assert(s != NULL && list != NULL); if(s != NULL && list != NULL) { *list = NULL; if ((ret = smb_tree_connect(s, "IPC$", &ipc_tid)) != DSM_SUCCESS) return ret; if ((ret = smb_fopen(s, ipc_tid, "\\srvsvc", SMB_MOD_READ | SMB_MOD_WRITE, &srvscv_fd)) != DSM_SUCCESS) return ret; //// Phase 1: // We bind a context or whatever for DCE/RPC req = smb_message_new(SMD_CMD_TRANS); if (!req) { ret = DSM_ERROR_GENERIC; goto error; } req->packet->header.tid = ipc_tid; rpc_len = 0xffff; SMB_MSG_INIT_PKT(trans); trans.wct = 16; trans.total_data_count = 72; trans.max_data_count = rpc_len; trans.param_offset = 84; trans.data_count = 72; trans.data_offset = 84; trans.setup_count = 2; trans.pipe_function = 0x26; trans.fid = SMB_FD_FID(srvscv_fd); trans.bct = 89; SMB_MSG_PUT_PKT(req, trans); smb_message_put8(req, 0); // Padding smb_message_put_utf16(req, "\\PIPE\\", strlen("\\PIPE\\") + 1); smb_message_put16(req, 0); // Padding to be aligned with wtf boundary :-/ // Now we'll 'build' the DCE/RPC Packet. This basically a copycat // from wireshark values. smb_message_put8(req, 5); // version major smb_message_put8(req, 0); // minor smb_message_put8(req, 0x0b); // Packet type = 'bind' smb_message_put8(req, 0x03); // Packet flags = ?? smb_message_put32(req, 0x10); // Representation = little endian/ASCII. Damn smb_message_put16(req, 72); // Data len again smb_message_put16(req, 0); // Auth len ? smb_message_put32(req, 19); // Call ID ? smb_message_put16(req, rpc_len); // Max Xmit size smb_message_put16(req, rpc_len); // Max Recv size smb_message_put32(req, 0); // Assoc group ? smb_message_put32(req, 1); // Num Ctx Item // Adding the CtxItem, whatever could that be smb_message_put16(req, 0); // ContextID smb_message_put16(req, 1); // Num Trans Item // SRVSVC UUID const uint8_t uuid_e[8] = {0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e, 0xe1, 0x88}; smb_message_put_uuid(req, 0x4b324fc8, 0x1670, 0x01d3, uuid_e); smb_message_put16(req, 3); // Version smb_message_put16(req, 0); // Minor // Another UUID const uint8_t uuid_e2[8] = {0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60}; smb_message_put_uuid(req, 0x8a885d04, 0x1ceb, 0x11c9, uuid_e2); smb_message_put32(req, 2); // Another version // Let's send this ugly pile of shit over the network ! res = smb_session_send_msg(s, req); smb_message_destroy(req); if (!res) { ret = DSM_ERROR_NETWORK; goto error; } // Is the server throwing pile of shit back at me ? res = smb_session_recv_msg(s, &resp); if (!res || resp.packet->payload[68]) { BDSM_dbg("Bind call failed: 0x%hhx (reason = 0x%hhx)\n", resp.packet->payload[68], resp.packet->payload[70]); ret = DSM_ERROR_NETWORK; goto error; } //// Phase 2: // Now we have the 'bind' done (regarless of what it is), we'll call // NetShareEnumAll req = smb_message_new(SMD_CMD_TRANS); if (!req) { ret = DSM_ERROR_GENERIC; goto error; } req->packet->header.tid = ipc_tid; // this struct will be set at the end when we know the data size SMB_MSG_ADVANCE_PKT(req, smb_trans_req); smb_message_put8(req, 0); // Padding smb_message_put_utf16(req, "\\PIPE\\", strlen("\\PIPE\\") + 1); smb_message_put16(req, 0); // Padding // Now we'll 'build' the DCE/RPC Packet. This basically a copycat // from wireshark values. smb_message_put8(req, 5); // version major smb_message_put8(req, 0); // minor smb_message_put8(req, 0); // Packet type = 'request' smb_message_put8(req, 0x03); // Packet flags = ?? smb_message_put32(req, 0x10); // Representation = little endian/ASCII. Damn // Let's save the cursor here to update that later frag_len_cursor = req->cursor; smb_message_put16(req, 0); // Data len again (frag length) smb_message_put16(req, 0); // Auth len ? smb_message_put32(req, 12); // Call ID ? smb_message_put32(req, 64); // Alloc hint ? smb_message_put16(req, 0); // Context ID ? smb_message_put16(req, 15); // OpNum = NetShareEnumAll // Pointer to server UNC smb_message_put32(req, 0x00020000); // Referent ID ? smb_message_put32(req, strlen(s->srv.name) + 1); // Max count smb_message_put32(req, 0); // Offset smb_message_put32(req, strlen(s->srv.name) + 1); // Actual count // The server name, supposed to be downcased smb_message_put_utf16(req, s->srv.name, strlen(s->srv.name) + 1); if ((strlen(s->srv.name) % 2) == 0) // It won't be aligned with the terminating byte smb_message_put16(req, 0); smb_message_put32(req, 1); // Level 1 ? smb_message_put32(req, 1); // Ctr ? smb_message_put32(req, 0x00020004); // Referent ID ? smb_message_put64(req, 0); // Count/Null Pointer to NetShareInfo1 smb_message_put32(req, 0xffffffff); // Max Buffer (0xffffffff required by smbX) smb_message_put32(req, 0x00020008); // Referent ID ? smb_message_put32(req, 0); // Resume ? // fill trans pkt at the end since we know the size at the end SMB_MSG_INIT_PKT(trans); trans.wct = 16; trans.max_data_count = 4280; trans.setup_count = 2; trans.pipe_function = 0x26; // TransactNmPipe; trans.fid = SMB_FD_FID(srvscv_fd); trans.bct = req->cursor - sizeof(smb_trans_req); trans.data_count = trans.bct - 17; // 17 -> padding + \PIPE\ + padding trans.total_data_count = trans.data_count; trans.data_offset = 84; trans.param_offset = 84; // but insert it at the begining SMB_MSG_INSERT_PKT(req, 0, trans); req->packet->payload[frag_len_cursor] = trans.data_count; // (data_count SHOULD stay < 256) // Let's send this ugly pile of shit over the network ! res = smb_session_send_msg(s, req); smb_message_destroy(req); if (!res) { ret = DSM_ERROR_NETWORK; goto error; } // Is the server throwing pile of shit back at me ? res = smb_session_recv_msg(s, &resp); if (!res && (uint32_t)resp.packet->payload[resp.payload_size - 4]) { BDSM_dbg("NetShareEnumAll call failed.\n"); ret = DSM_ERROR_NETWORK; goto error; } //// Phase 3 // We parse the list of Share (finally !) and build function response count = smb_share_parse_enum(&resp, list); if (count == -1) { ret = DSM_ERROR_GENERIC; goto error; } if (pcount != NULL) *pcount = count; ret = DSM_SUCCESS; error: // Close the pipe smb_fclose(s, srvscv_fd); return ret; } ret = DSM_ERROR_GENERIC; }