/**************************************************************************** find first available connection slot, starting from a random position. The randomisation stops problems with the server dieing and clients thinking the server is still available. ****************************************************************************/ connection_struct *conn_new(void) { connection_struct *conn; int i; i = bitmap_find(bmap, 1); if (i == -1) { DEBUG(1,("ERROR! Out of connection structures\n")); return NULL; } conn = (connection_struct *)malloc(sizeof(*conn)); if (!conn) return NULL; ZERO_STRUCTP(conn); conn->cnum = i; bitmap_set(bmap, i); num_open++; string_set(&conn->user,""); string_set(&conn->dirpath,""); string_set(&conn->connectpath,""); string_set(&conn->origpath,""); DLIST_ADD(Connections, conn); return conn; }
/**************************************************************************** find first available policy slot. creates a policy handle for you. ****************************************************************************/ BOOL open_lsa_policy_hnd(POLICY_HND *hnd) { int i; struct policy *p; i = bitmap_find(bmap, 1); if (i == -1) { DEBUG(0,("ERROR: out of Policy Handles!\n")); return False; } p = (struct policy *)malloc(sizeof(*p)); if (!p) { DEBUG(0,("ERROR: out of memory!\n")); return False; } ZERO_STRUCTP(p); p->open = True; p->pnum = i; create_pol_hnd(hnd); memcpy(&p->pol_hnd, hnd, sizeof(*hnd)); bitmap_set(bmap, i); DLIST_ADD(Policy, p); DEBUG(4,("Opened policy hnd[%x] ", i)); dump_data(4, (char *)hnd->data, sizeof(hnd->data)); return True; }
NTSTATUS file_new(struct smb_request *req, connection_struct *conn, files_struct **result) { int i; files_struct *fsp; NTSTATUS status; /* we want to give out file handles differently on each new connection because of a common bug in MS clients where they try to reuse a file descriptor from an earlier smb connection. This code increases the chance that the errant client will get an error rather than causing corruption */ if (first_file == 0) { first_file = (sys_getpid() ^ (int)time(NULL)) % real_max_open_files; } /* TODO: Port the id-tree implementation from Samba4 */ i = bitmap_find(file_bmap, first_file); if (i == -1) { DEBUG(0,("ERROR! Out of file structures\n")); /* TODO: We have to unconditionally return a DOS error here, * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with * NTSTATUS negotiated */ return NT_STATUS_TOO_MANY_OPENED_FILES; } /* * Make a child of the connection_struct as an fsp can't exist * indepenedent of a connection. */ fsp = talloc_zero(conn, struct files_struct); if (!fsp) { return NT_STATUS_NO_MEMORY; } /* * This can't be a child of fsp because the file_handle can be ref'd * when doing a dos/fcb open, which will then share the file_handle * across multiple fsps. */ fsp->fh = talloc_zero(conn, struct fd_handle); if (!fsp->fh) { TALLOC_FREE(fsp); return NT_STATUS_NO_MEMORY; } fsp->fh->ref_count = 1; fsp->fh->fd = -1; fsp->conn = conn; fsp->fh->gen_id = get_gen_count(); GetTimeOfDay(&fsp->open_time); first_file = (i+1) % real_max_open_files; bitmap_set(file_bmap, i); files_used++; fsp->fnum = i + FILE_HANDLE_OFFSET; SMB_ASSERT(fsp->fnum < 65536); /* * Create an smb_filename with "" for the base_name. There are very * few NULL checks, so make sure it's initialized with something. to * be safe until an audit can be done. */ status = create_synthetic_smb_fname(fsp, "", NULL, NULL, &fsp->fsp_name); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(fsp); TALLOC_FREE(fsp->fh); } DLIST_ADD(Files, fsp); DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n", i, fsp->fnum, files_used)); if (req != NULL) { req->chain_fsp = fsp; } /* A new fsp invalidates the positive and negative fsp_fi_cache as the new fsp is pushed at the start of the list and we search from a cache hit to the *end* of the list. */ ZERO_STRUCT(fsp_fi_cache); conn->num_files_open++; *result = fsp; return NT_STATUS_OK; }
NTSTATUS file_new(struct smb_request *req, connection_struct *conn, files_struct **result) { int i; files_struct *fsp; /* we want to give out file handles differently on each new connection because of a common bug in MS clients where they try to reuse a file descriptor from an earlier smb connection. This code increases the chance that the errant client will get an error rather than causing corruption */ if (first_file == 0) { first_file = (sys_getpid() ^ (int)time(NULL)) % real_max_open_files; } /* TODO: Port the id-tree implementation from Samba4 */ i = bitmap_find(file_bmap, first_file); if (i == -1) { DEBUG(0,("ERROR! Out of file structures\n")); /* TODO: We have to unconditionally return a DOS error here, * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with * NTSTATUS negotiated */ return NT_STATUS_TOO_MANY_OPENED_FILES; } fsp = SMB_MALLOC_P(files_struct); if (!fsp) { return NT_STATUS_NO_MEMORY; } ZERO_STRUCTP(fsp); fsp->fh = SMB_MALLOC_P(struct fd_handle); if (!fsp->fh) { SAFE_FREE(fsp); return NT_STATUS_NO_MEMORY; } ZERO_STRUCTP(fsp->fh); fsp->fh->ref_count = 1; fsp->fh->fd = -1; fsp->conn = conn; fsp->fh->gen_id = get_gen_count(); GetTimeOfDay(&fsp->open_time); first_file = (i+1) % real_max_open_files; bitmap_set(file_bmap, i); files_used++; fsp->fnum = i + FILE_HANDLE_OFFSET; SMB_ASSERT(fsp->fnum < 65536); string_set(&fsp->fsp_name,""); DLIST_ADD(Files, fsp); DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n", i, fsp->fnum, files_used)); if (req != NULL) { req->chain_fsp = fsp; } /* A new fsp invalidates the positive and negative fsp_fi_cache as the new fsp is pushed at the start of the list and we search from a cache hit to the *end* of the list. */ ZERO_STRUCT(fsp_fi_cache); conn->num_files_open++; *result = fsp; return NT_STATUS_OK; }
pipes_struct *open_rpc_pipe_p(char *pipe_name, connection_struct *conn, uint16 vuid) { int i; pipes_struct *p; static int next_pipe; DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n", pipe_name, pipes_open)); /* not repeating pipe numbers makes it easier to track things in log files and prevents client bugs where pipe numbers are reused over connection restarts */ if (next_pipe == 0) next_pipe = (getpid() ^ time(NULL)) % MAX_OPEN_PIPES; i = bitmap_find(bmap, next_pipe); if (i == -1) { DEBUG(0,("ERROR! Out of pipe structures\n")); return NULL; } next_pipe = (i+1) % MAX_OPEN_PIPES; for (p = Pipes; p; p = p->next) DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum)); p = (pipes_struct *)malloc(sizeof(*p)); if (!p) return NULL; ZERO_STRUCTP(p); DLIST_ADD(Pipes, p); /* * Initialize the incoming RPC data buffer with one PDU worth of memory. * We cheat here and say we're marshalling, as we intend to add incoming * data directly into the prs_struct and we want it to auto grow. We will * change the type to UNMARSALLING before processing the stream. */ if(!prs_init(&p->in_data.data, MAX_PDU_FRAG_LEN, 4, MARSHALL)) { DEBUG(0,("open_rpc_pipe_p: malloc fail for in_data struct.\n")); return NULL; } bitmap_set(bmap, i); i += pipe_handle_offset; pipes_open++; p->pnum = i; p->open = True; p->device_state = 0; p->priority = 0; p->conn = conn; p->vuid = vuid; p->max_trans_reply = 0; p->ntlmssp_chal_flags = 0; p->ntlmssp_auth_validated = False; p->ntlmssp_auth_requested = False; p->pipe_bound = False; p->fault_state = False; /* * Initialize the incoming RPC struct. */ p->in_data.pdu_needed_len = 0; p->in_data.pdu_received_len = 0; /* * Initialize the outgoing RPC struct. */ p->out_data.current_pdu_len = 0; p->out_data.current_pdu_sent = 0; p->out_data.data_sent_length = 0; /* * Initialize the outgoing RPC data buffer with no memory. */ prs_init(&p->out_data.rdata, 0, 4, MARSHALL); p->uid = (uid_t)-1; p->gid = (gid_t)-1; fstrcpy(p->name, pipe_name); DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n", pipe_name, i, pipes_open)); chain_p = p; /* OVERWRITE p as a temp variable, to display all open pipes */ for (p = Pipes; p; p = p->next) DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum)); return chain_p; }
smb_np_struct *open_rpc_pipe_p(char *pipe_name, connection_struct *conn, uint16 vuid) { int i; smb_np_struct *p, *p_it; static int next_pipe; BOOL is_spoolss_pipe = False; DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n", pipe_name, pipes_open)); if (strstr(pipe_name, "spoolss")) { is_spoolss_pipe = True; } if (is_spoolss_pipe && current_spoolss_pipes_open >= MAX_OPEN_SPOOLSS_PIPES) { DEBUG(10,("open_rpc_pipe_p: spooler bug workaround. Denying open on pipe %s\n", pipe_name )); return NULL; } /* not repeating pipe numbers makes it easier to track things in log files and prevents client bugs where pipe numbers are reused over connection restarts */ if (next_pipe == 0) { next_pipe = (sys_getpid() ^ time(NULL)) % MAX_OPEN_PIPES; } i = bitmap_find(bmap, next_pipe); if (i == -1) { DEBUG(0,("ERROR! Out of pipe structures\n")); return NULL; } next_pipe = (i+1) % MAX_OPEN_PIPES; for (p = Pipes; p; p = p->next) { DEBUG(5,("open_rpc_pipe_p: name %s pnum=%x\n", p->name, p->pnum)); } p = SMB_MALLOC_P(smb_np_struct); if (!p) { DEBUG(0,("ERROR! no memory for pipes_struct!\n")); return NULL; } ZERO_STRUCTP(p); /* add a dso mechanism instead of this, here */ p->namedpipe_create = make_internal_rpc_pipe_p; p->namedpipe_read = read_from_internal_pipe; p->namedpipe_write = write_to_internal_pipe; p->namedpipe_close = close_internal_rpc_pipe_hnd; p->np_state = p->namedpipe_create(pipe_name, conn, vuid); if (p->np_state == NULL) { DEBUG(0,("open_rpc_pipe_p: make_internal_rpc_pipe_p failed.\n")); SAFE_FREE(p); return NULL; } DLIST_ADD(Pipes, p); /* * Initialize the incoming RPC data buffer with one PDU worth of memory. * We cheat here and say we're marshalling, as we intend to add incoming * data directly into the prs_struct and we want it to auto grow. We will * change the type to UNMARSALLING before processing the stream. */ bitmap_set(bmap, i); i += pipe_handle_offset; pipes_open++; p->pnum = i; p->open = True; p->device_state = 0; p->priority = 0; p->conn = conn; p->vuid = vuid; p->max_trans_reply = 0; fstrcpy(p->name, pipe_name); DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n", pipe_name, i, pipes_open)); chain_p = p; /* Iterate over p_it as a temp variable, to display all open pipes */ for (p_it = Pipes; p_it; p_it = p_it->next) { DEBUG(5,("open pipes: name %s pnum=%x\n", p_it->name, p_it->pnum)); } return chain_p; }
/**************************************************************************** find first available connection slot, starting from a random position. The randomisation stops problems with the server dieing and clients thinking the server is still available. ****************************************************************************/ connection_struct *conn_new(void) { TALLOC_CTX *mem_ctx; connection_struct *conn; int i; int find_offset = 1; find_again: i = bitmap_find(bmap, find_offset); if (i == -1) { /* Expand the connections bitmap. */ int oldsz = bmap->n; int newsz = bmap->n + BITMAP_BLOCK_SZ; struct bitmap * nbmap; if (newsz <= 0) { /* Integer wrap. */ DEBUG(0,("ERROR! Out of connection structures\n")); return NULL; } DEBUG(4,("resizing connections bitmap from %d to %d\n", oldsz, newsz)); nbmap = bitmap_allocate(newsz); if (!nbmap) { DEBUG(0,("ERROR! malloc fail.\n")); return NULL; } bitmap_copy(nbmap, bmap); bitmap_free(bmap); bmap = nbmap; find_offset = oldsz; /* Start next search in the new portion. */ goto find_again; } if ((mem_ctx=talloc_init("connection_struct"))==NULL) { DEBUG(0,("talloc_init(connection_struct) failed!\n")); return NULL; } if ((conn=TALLOC_ZERO_P(mem_ctx, connection_struct))==NULL) { DEBUG(0,("talloc_zero() failed!\n")); return NULL; } conn->mem_ctx = mem_ctx; conn->cnum = i; bitmap_set(bmap, i); num_open++; string_set(&conn->user,""); string_set(&conn->dirpath,""); string_set(&conn->connectpath,""); string_set(&conn->origpath,""); DLIST_ADD(Connections, conn); return conn; }