/* * Do some module- and library-wide intializations */ static void SMBC_module_init(void * punused) { bool conf_loaded = False; char *home = NULL; TALLOC_CTX *frame = talloc_stackframe(); load_case_tables_library(); setup_logging("libsmbclient", DEBUG_STDOUT); /* Here we would open the smb.conf file if needed ... */ home = getenv("HOME"); if (home) { char *conf = NULL; if (asprintf(&conf, "%s/.smb/smb.conf", home) > 0) { if (lp_load_client(conf)) { conf_loaded = True; } else { DEBUG(5, ("Could not load config file: %s\n", conf)); } SAFE_FREE(conf); } } if (!conf_loaded) { /* * Well, if that failed, try the get_dyn_CONFIGFILE * Which points to the standard locn, and if that * fails, silently ignore it and use the internal * defaults ... */ if (!lp_load_client(get_dyn_CONFIGFILE())) { DEBUG(5, ("Could not load config file: %s\n", get_dyn_CONFIGFILE())); } else if (home) { char *conf; /* * We loaded the global config file. Now lets * load user-specific modifications to the * global config. */ if (asprintf(&conf, "%s/.smb/smb.conf.append", home) > 0) { if (!lp_load_client_no_reinit(conf)) { DEBUG(10, ("Could not append config file: " "%s\n", conf)); } SAFE_FREE(conf); } } } load_interfaces(); /* Load the list of interfaces ... */ reopen_logs(); /* Get logging working ... */ /* * Block SIGPIPE (from lib/util_sock.c: write()) * It is not needed and should not stop execution */ BlockSignals(True, SIGPIPE); /* Create the mutex we'll use to protect initialized_ctx_count */ if (SMB_THREAD_CREATE_MUTEX("initialized_ctx_count_mutex", initialized_ctx_count_mutex) != 0) { smb_panic("SMBC_module_init: " "failed to create 'initialized_ctx_count' mutex"); } TALLOC_FREE(frame); }
/** * Check whether the given password is one of the last two * password history entries. If so, the bad pwcount should * not be incremented even thought the actual password check * failed. */ static bool need_to_increment_bad_pw_count( const DATA_BLOB *challenge, struct samu* sampass, const struct auth_usersupplied_info *user_info) { uint8_t i; const uint8_t *pwhistory; uint32_t pwhistory_len; uint32_t policy_pwhistory_len; uint32_t acct_ctrl; const char *username; TALLOC_CTX *mem_ctx = talloc_stackframe(); bool result = true; pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &policy_pwhistory_len); if (policy_pwhistory_len == 0) { goto done; } pwhistory = pdb_get_pw_history(sampass, &pwhistory_len); if (!pwhistory || pwhistory_len == 0) { goto done; } acct_ctrl = pdb_get_acct_ctrl(sampass); username = pdb_get_username(sampass); for (i=1; i < MIN(MIN(3, policy_pwhistory_len), pwhistory_len); i++) { static const uint8_t zero16[SALTED_MD5_HASH_LEN]; const uint8_t *salt; const uint8_t *nt_pw; NTSTATUS status; DATA_BLOB user_sess_key = data_blob_null; DATA_BLOB lm_sess_key = data_blob_null; salt = &pwhistory[i*PW_HISTORY_ENTRY_LEN]; nt_pw = salt + PW_HISTORY_SALT_LEN; if (memcmp(zero16, nt_pw, NT_HASH_LEN) == 0) { /* skip zero password hash */ continue; } if (memcmp(zero16, salt, PW_HISTORY_SALT_LEN) != 0) { /* skip nonzero salt (old format entry) */ continue; } status = sam_password_ok(mem_ctx, username, acct_ctrl, challenge, NULL, nt_pw, user_info, &user_sess_key, &lm_sess_key); if (NT_STATUS_IS_OK(status)) { result = false; break; } } done: TALLOC_FREE(mem_ctx); return result; }
int main(int argc, const char **argv) { const char *config_file = get_dyn_CONFIGFILE(); int ret = 0; poptContext pc; char *count_str = NULL; int i, count = 1; struct poptOption long_options[] = { POPT_AUTOHELP {"count", 'c', POPT_ARG_STRING, &count_str, 1, "Load config <count> number of times"}, POPT_COMMON_DEBUGLEVEL POPT_TABLEEND }; TALLOC_CTX *frame = talloc_stackframe(); load_case_tables(); DEBUGLEVEL_CLASS[DBGC_ALL] = 0; pc = poptGetContext(NULL, argc, argv, long_options, POPT_CONTEXT_KEEP_FIRST); poptSetOtherOptionHelp(pc, "[OPTION...] <config-file>"); while(poptGetNextOpt(pc) != -1); setup_logging(poptGetArg(pc), True); if (poptPeekArg(pc)) { config_file = poptGetArg(pc); } poptFreeContext(pc); if (count_str != NULL) { count = atoi(count_str); } dbf = x_stderr; /* Don't let the debuglevel be changed by smb.conf. */ AllowDebugChange = False; for (i=0; i < count; i++) { printf("call lp_load() #%d: ", i+1); if (!lp_load_with_registry_shares(config_file, False, /* global only */ True, /* save defaults */ False, /*add_ipc */ True)) /*init globals */ { printf("ERROR.\n"); ret = 1; goto done; } printf("ok.\n"); } done: gfree_loadparm(); TALLOC_FREE(frame); return ret; }
/** * Get the values of a key as a list of value names * and a list of value strings (ordered) */ static sbcErr smbconf_reg_get_values(TALLOC_CTX *mem_ctx, struct registry_key *key, uint32_t *num_values, char ***value_names, char ***value_strings) { TALLOC_CTX *tmp_ctx = NULL; WERROR werr = WERR_OK; sbcErr err; uint32_t count; struct registry_value *valvalue = NULL; char *valname = NULL; uint32_t tmp_num_values = 0; char **tmp_valnames = NULL; char **tmp_valstrings = NULL; uint32_t num_includes = 0; char **includes = NULL; if ((num_values == NULL) || (value_names == NULL) || (value_strings == NULL)) { err = SBC_ERR_INVALID_PARAM; goto done; } tmp_ctx = talloc_stackframe(); for (count = 0; werr = reg_enumvalue(tmp_ctx, key, count, &valname, &valvalue), W_ERROR_IS_OK(werr); count++) { char *valstring; if (!smbconf_reg_valname_valid(valname)) { continue; } err = smbconf_add_string_to_array(tmp_ctx, &tmp_valnames, tmp_num_values, valname); if (!SBC_ERROR_IS_OK(err)) { goto done; } valstring = smbconf_format_registry_value(tmp_ctx, valvalue); err = smbconf_add_string_to_array(tmp_ctx, &tmp_valstrings, tmp_num_values, valstring); if (!SBC_ERROR_IS_OK(err)) { goto done; } tmp_num_values++; } if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) { err = SBC_ERR_NOMEM; goto done; } /* now add the includes at the end */ err = smbconf_reg_get_includes_internal(tmp_ctx, key, &num_includes, &includes); if (!SBC_ERROR_IS_OK(err)) { goto done; } for (count = 0; count < num_includes; count++) { err = smbconf_add_string_to_array(tmp_ctx, &tmp_valnames, tmp_num_values, "include"); if (!SBC_ERROR_IS_OK(err)) { goto done; } err = smbconf_add_string_to_array(tmp_ctx, &tmp_valstrings, tmp_num_values, includes[count]); if (!SBC_ERROR_IS_OK(err)) { goto done; } tmp_num_values++; } *num_values = tmp_num_values; if (tmp_num_values > 0) { *value_names = talloc_move(mem_ctx, &tmp_valnames); *value_strings = talloc_move(mem_ctx, &tmp_valstrings); } else { *value_names = NULL; *value_strings = NULL; } done: talloc_free(tmp_ctx); return err; }
int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32_t, const char *, void *), void *state) { char *rparam = NULL; char *rdata = NULL; char *p; unsigned int rdrcnt,rprcnt; char param[1024]; int count = -1; /* now send a SMBtrans command with api RNetShareEnum */ p = param; SSVAL(p,0,0); /* api number */ p += 2; strlcpy(p,"WrLeh",sizeof(param)-PTR_DIFF(p,param)); p = skip_string(param,sizeof(param),p); strlcpy(p,"B13BWz",sizeof(param)-PTR_DIFF(p,param)); p = skip_string(param,sizeof(param),p); SSVAL(p,0,1); /* * Win2k needs a *smaller* buffer than 0xFFFF here - * it returns "out of server memory" with 0xFFFF !!! JRA. */ SSVAL(p,2,0xFFE0); p += 4; if (cli_api(cli, param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */ NULL, 0, 0xFFE0, /* data, length, maxlen - Win2k needs a small buffer here too ! */ &rparam, &rprcnt, /* return params, length */ &rdata, &rdrcnt)) /* return data, length */ { int res = rparam? SVAL(rparam,0) : -1; if (res == 0 || res == ERRmoredata) { int converter=SVAL(rparam,2); int i; char *rdata_end = rdata + rdrcnt; count=SVAL(rparam,4); p = rdata; for (i=0;i<count;i++,p+=20) { char *sname; int type; int comment_offset; const char *cmnt; const char *p1; char *s1, *s2; size_t len; TALLOC_CTX *frame = talloc_stackframe(); if (p + 20 > rdata_end) { TALLOC_FREE(frame); break; } sname = p; type = SVAL(p,14); comment_offset = (IVAL(p,16) & 0xFFFF) - converter; if (comment_offset < 0 || comment_offset > (int)rdrcnt) { TALLOC_FREE(frame); break; } cmnt = comment_offset?(rdata+comment_offset):""; /* Work out the comment length. */ for (p1 = cmnt, len = 0; *p1 && p1 < rdata_end; len++) p1++; if (!*p1) { len++; } pull_string_talloc(frame,rdata,0, &s1,sname,14,STR_ASCII); pull_string_talloc(frame,rdata,0, &s2,cmnt,len,STR_ASCII); if (!s1 || !s2) { TALLOC_FREE(frame); continue; } fn(s1, type, s2, state); TALLOC_FREE(frame); } } else { DEBUG(4,("NetShareEnum res=%d\n", res)); } } else { DEBUG(4,("NetShareEnum failed\n")); } SAFE_FREE(rparam); SAFE_FREE(rdata); return count; }
static bool irix_oplocks_available(void) { int fd; int pfd[2]; TALLOC_CTX *ctx = talloc_stackframe(); char *tmpname = NULL; set_effective_capability(KERNEL_OPLOCK_CAPABILITY); tmpname = talloc_asprintf(ctx, "%s/koplock.%d", lp_lockdir(), (int)getpid()); if (!tmpname) { TALLOC_FREE(ctx); return False; } if(pipe(pfd) != 0) { DEBUG(0,("check_kernel_oplocks: Unable to create pipe. Error " "was %s\n", strerror(errno) )); TALLOC_FREE(ctx); return False; } if((fd = open(tmpname, O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0600)) < 0) { DEBUG(0,("check_kernel_oplocks: Unable to open temp test file " "%s. Error was %s\n", tmpname, strerror(errno) )); unlink( tmpname ); close(pfd[0]); close(pfd[1]); TALLOC_FREE(ctx); return False; } unlink(tmpname); TALLOC_FREE(ctx); if(sys_fcntl_long(fd, F_OPLKREG, pfd[1]) == -1) { DEBUG(0,("check_kernel_oplocks: Kernel oplocks are not " "available on this machine. Disabling kernel oplock " "support.\n" )); close(pfd[0]); close(pfd[1]); close(fd); return False; } if(sys_fcntl_long(fd, F_OPLKACK, OP_REVOKE) < 0 ) { DEBUG(0,("check_kernel_oplocks: Error when removing kernel " "oplock. Error was %s. Disabling kernel oplock " "support.\n", strerror(errno) )); close(pfd[0]); close(pfd[1]); close(fd); return False; } close(pfd[0]); close(pfd[1]); close(fd); return True; }
int main(int argc, const char **argv) { poptContext pc; int opt; struct tevent_context *evt_ctx; struct messaging_context *msg_ctx; static struct poptOption long_options[] = { /* POPT_AUTOHELP */ { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options, 0, "Help options:", NULL }, { "timeout", 't', POPT_ARG_INT, &timeout, 't', "Set timeout value in seconds", "TIMEOUT" }, POPT_COMMON_SAMBA POPT_TABLEEND }; TALLOC_CTX *frame = talloc_stackframe(); int ret = 0; load_case_tables(); setup_logging(argv[0],True); /* Parse command line arguments using popt */ pc = poptGetContext( "smbcontrol", argc, (const char **)argv, long_options, 0); poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> " "<parameters>"); if (argc == 1) usage(pc); while ((opt = poptGetNextOpt(pc)) != -1) { switch(opt) { case 't': /* --timeout */ break; default: fprintf(stderr, "Invalid option\n"); poptPrintHelp(pc, stderr, 0); break; } } /* We should now have the remaining command line arguments in argv. The argc parameter should have been decremented to the correct value in the above switch statement. */ argv = (const char **)poptGetArgs(pc); argc = 0; if (argv != NULL) { while (argv[argc] != NULL) { argc++; } } if (argc <= 1) usage(pc); lp_load(get_dyn_CONFIGFILE(),False,False,False,True); /* Need to invert sense of return code -- samba * routines mostly return True==1 for success, but * shell needs 0. */ if (!(evt_ctx = tevent_context_init(NULL)) || !(msg_ctx = messaging_init(NULL, server_id_self(), evt_ctx))) { fprintf(stderr, "could not init messaging context\n"); TALLOC_FREE(frame); exit(1); } ret = !do_command(msg_ctx, argc, argv); TALLOC_FREE(frame); return ret; }
SMBCFILE * SMBC_open_ctx(SMBCCTX *context, const char *fname, int flags, mode_t mode) { char *server = NULL; char *share = NULL; char *user = NULL; char *password = NULL; char *workgroup = NULL; char *path = NULL; char *targetpath = NULL; struct cli_state *targetcli = NULL; SMBCSRV *srv = NULL; SMBCFILE *file = NULL; uint16_t fd; uint16_t port = 0; NTSTATUS status = NT_STATUS_OBJECT_PATH_INVALID; TALLOC_CTX *frame = talloc_stackframe(); if (!context || !context->internal->initialized) { errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); return NULL; } if (!fname) { errno = EINVAL; TALLOC_FREE(frame); return NULL; } if (SMBC_parse_path(frame, context, fname, &workgroup, &server, &port, &share, &path, &user, &password, NULL)) { errno = EINVAL; TALLOC_FREE(frame); return NULL; } if (!user || user[0] == (char)0) { user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); return NULL; } } srv = SMBC_server(frame, context, True, server, port, share, &workgroup, &user, &password); if (!srv) { if (errno == EPERM) errno = EACCES; TALLOC_FREE(frame); return NULL; /* SMBC_server sets errno */ } /* Hmmm, the test for a directory is suspect here ... FIXME */ if (strlen(path) > 0 && path[strlen(path) - 1] == '\\') { status = NT_STATUS_OBJECT_PATH_INVALID; } else { file = SMB_MALLOC_P(SMBCFILE); if (!file) { errno = ENOMEM; TALLOC_FREE(frame); return NULL; } ZERO_STRUCTP(file); /*d_printf(">>>open: resolving %s\n", path);*/ status = cli_resolve_path( frame, "", context->internal->auth_info, srv->cli, path, &targetcli, &targetpath); if (!NT_STATUS_IS_OK(status)) { d_printf("Could not resolve %s\n", path); errno = ENOENT; SAFE_FREE(file); TALLOC_FREE(frame); return NULL; } /*d_printf(">>>open: resolved %s as %s\n", path, targetpath);*/ status = cli_open(targetcli, targetpath, flags, context->internal->share_mode, &fd); if (!NT_STATUS_IS_OK(status)) { /* Handle the error ... */ SAFE_FREE(file); errno = SMBC_errno(context, targetcli); TALLOC_FREE(frame); return NULL; } /* Fill in file struct */ file->cli_fd = fd; file->fname = SMB_STRDUP(fname); file->srv = srv; file->offset = 0; file->file = True; DLIST_ADD(context->internal->files, file); /* * If the file was opened in O_APPEND mode, all write * operations should be appended to the file. To do that, * though, using this protocol, would require a getattrE() * call for each and every write, to determine where the end * of the file is. (There does not appear to be an append flag * in the protocol.) Rather than add all of that overhead of * retrieving the current end-of-file offset prior to each * write operation, we'll assume that most append operations * will continuously write, so we'll just set the offset to * the end of the file now and hope that's adequate. * * Note to self: If this proves inadequate, and O_APPEND * should, in some cases, be forced for each write, add a * field in the context options structure, for * "strict_append_mode" which would select between the current * behavior (if FALSE) or issuing a getattrE() prior to each * write and forcing the write to the end of the file (if * TRUE). Adding that capability will likely require adding * an "append" flag into the _SMBCFILE structure to track * whether a file was opened in O_APPEND mode. -- djl */ if (flags & O_APPEND) { if (SMBC_lseek_ctx(context, file, 0, SEEK_END) < 0) { (void) SMBC_close_ctx(context, file); errno = ENXIO; TALLOC_FREE(frame); return NULL; } } TALLOC_FREE(frame); return file; } /* Check if opendir needed ... */ if (!NT_STATUS_IS_OK(status)) { int eno = 0; eno = SMBC_errno(context, srv->cli); file = smbc_getFunctionOpendir(context)(context, fname); if (!file) errno = eno; TALLOC_FREE(frame); return file; } errno = EINVAL; /* FIXME, correct errno ? */ TALLOC_FREE(frame); return NULL; }
ssize_t SMBC_write_ctx(SMBCCTX *context, SMBCFILE *file, const void *buf, size_t count) { off_t offset; char *server = NULL, *share = NULL, *user = NULL, *password = NULL; char *path = NULL; char *targetpath = NULL; struct cli_state *targetcli = NULL; uint16_t port = 0; TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; /* First check all pointers before dereferencing them */ if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; } /* Check that the buffer exists ... */ if (buf == NULL) { errno = EINVAL; TALLOC_FREE(frame); return -1; } offset = file->offset; /* See "offset" comment in SMBC_read_ctx() */ /*d_printf(">>>write: parsing %s\n", file->fname);*/ if (SMBC_parse_path(frame, context, file->fname, NULL, &server, &port, &share, &path, &user, &password, NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } /*d_printf(">>>write: resolving %s\n", path);*/ status = cli_resolve_path(frame, "", context->internal->auth_info, file->srv->cli, path, &targetcli, &targetpath); if (!NT_STATUS_IS_OK(status)) { d_printf("Could not resolve %s\n", path); errno = ENOENT; TALLOC_FREE(frame); return -1; } /*d_printf(">>>write: resolved path as %s\n", targetpath);*/ status = cli_writeall(targetcli, file->cli_fd, 0, (const uint8_t *)buf, offset, count, NULL); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); TALLOC_FREE(frame); return -1; } file->offset += count; TALLOC_FREE(frame); return count; /* Success, 0 bytes of data ... */ }
ssize_t SMBC_read_ctx(SMBCCTX *context, SMBCFILE *file, void *buf, size_t count) { size_t ret; char *server = NULL, *share = NULL, *user = NULL, *password = NULL; char *path = NULL; char *targetpath = NULL; struct cli_state *targetcli = NULL; uint16_t port = 0; TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; /* * offset: * * Compiler bug (possibly) -- gcc (GCC) 3.3.5 (Debian 1:3.3.5-2) -- * appears to pass file->offset (which is type off_t) differently than * a local variable of type off_t. Using local variable "offset" in * the call to cli_read() instead of file->offset fixes a problem * retrieving data at an offset greater than 4GB. */ off_t offset; if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } DEBUG(4, ("smbc_read(%p, %d)\n", file, (int)count)); if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; } offset = file->offset; /* Check that the buffer exists ... */ if (buf == NULL) { errno = EINVAL; TALLOC_FREE(frame); return -1; } /*d_printf(">>>read: parsing %s\n", file->fname);*/ if (SMBC_parse_path(frame, context, file->fname, NULL, &server, &port, &share, &path, &user, &password, NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } /*d_printf(">>>read: resolving %s\n", path);*/ status = cli_resolve_path(frame, "", context->internal->auth_info, file->srv->cli, path, &targetcli, &targetpath); if (!NT_STATUS_IS_OK(status)) { d_printf("Could not resolve %s\n", path); errno = ENOENT; TALLOC_FREE(frame); return -1; } /*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/ status = cli_read(targetcli, file->cli_fd, (char *)buf, offset, count, &ret); if (!NT_STATUS_IS_OK(status)) { errno = SMBC_errno(context, targetcli); TALLOC_FREE(frame); return -1; } file->offset += ret; DEBUG(4, (" --> %ld\n", (unsigned long)ret)); TALLOC_FREE(frame); return ret; /* Success, ret bytes of data ... */ }
off_t SMBC_splice_ctx(SMBCCTX *context, SMBCFILE *srcfile, SMBCFILE *dstfile, off_t count, int (*splice_cb)(off_t n, void *priv), void *priv) { off_t written; char *server = NULL, *share = NULL, *user = NULL, *password = NULL; char *path = NULL; char *targetpath = NULL; struct cli_state *srccli = NULL; struct cli_state *dstcli = NULL; uint16_t port = 0; TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } if (!srcfile || !SMBC_dlist_contains(context->internal->files, srcfile)) { errno = EBADF; TALLOC_FREE(frame); return -1; } if (!dstfile || !SMBC_dlist_contains(context->internal->files, dstfile)) { errno = EBADF; TALLOC_FREE(frame); return -1; } if (SMBC_parse_path(frame, context, srcfile->fname, NULL, &server, &port, &share, &path, &user, &password, NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } status = cli_resolve_path(frame, "", context->internal->auth_info, srcfile->srv->cli, path, &srccli, &targetpath); if (!NT_STATUS_IS_OK(status)) { d_printf("Could not resolve %s\n", path); errno = ENOENT; TALLOC_FREE(frame); return -1; } if (SMBC_parse_path(frame, context, dstfile->fname, NULL, &server, &port, &share, &path, &user, &password, NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } status = cli_resolve_path(frame, "", context->internal->auth_info, dstfile->srv->cli, path, &dstcli, &targetpath); if (!NT_STATUS_IS_OK(status)) { d_printf("Could not resolve %s\n", path); errno = ENOENT; TALLOC_FREE(frame); return -1; } status = cli_splice(srccli, dstcli, srcfile->cli_fd, dstfile->cli_fd, count, srcfile->offset, dstfile->offset, &written, splice_cb, priv); if (!NT_STATUS_IS_OK(status)) { errno = SMBC_errno(context, srccli); TALLOC_FREE(frame); return -1; } srcfile->offset += written; dstfile->offset += written; TALLOC_FREE(frame); return written; }
int do_smb_browse(void) { int mdnsfd; int fdsetsz; int ret; fd_set *fdset = NULL; struct mdns_browse_state bstate; struct mdns_smbsrv_result *resptr; struct timeval tv; DNSServiceRef mdns_conn_sdref = NULL; DNSServiceErrorType err; TALLOC_CTX * ctx = talloc_stackframe(); ZERO_STRUCT(bstate); err = DNSServiceBrowse(&mdns_conn_sdref, 0, 0, "_smb._tcp", "", do_smb_browse_reply, &bstate); if (err != kDNSServiceErr_NoError) { d_printf("Error connecting to the Multicast DNS daemon\n"); TALLOC_FREE(ctx); return 1; } mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref); for (;;) { if (fdset != NULL) { TALLOC_FREE(fdset); } fdsetsz = howmany(mdnsfd + 1, NFDBITS) * sizeof(fd_mask); fdset = TALLOC_ZERO(ctx, fdsetsz); FD_SET(mdnsfd, fdset); tv.tv_sec = 1; tv.tv_usec = 0; /* Wait until response received from mDNS daemon */ ret = sys_select(mdnsfd + 1, fdset, NULL, NULL, &tv); if (ret <= 0 && errno != EINTR) { break; } if (FD_ISSET(mdnsfd, fdset)) { /* Invoke callback function */ if (DNSServiceProcessResult(mdns_conn_sdref)) { break; } if (bstate.browseDone) { break; } } } DNSServiceRefDeallocate(mdns_conn_sdref); if (bstate.listhead != NULL) { resptr = bstate.listhead; while (resptr != NULL) { struct mdns_smbsrv_result *oldresptr; oldresptr = resptr; /* Resolve smb service instance */ do_smb_resolve(resptr); resptr = resptr->nextResult; } } TALLOC_FREE(ctx); return 0; }
static bool tdbsam_convert_backup(const char *dbname, struct db_context **pp_db) { TALLOC_CTX *frame = talloc_stackframe(); const char *tmp_fname = NULL; struct db_context *tmp_db = NULL; struct db_context *orig_db = *pp_db; struct tdbsam_backup_state bs; int ret; tmp_fname = talloc_asprintf(frame, "%s.tmp", dbname); if (!tmp_fname) { TALLOC_FREE(frame); return false; } unlink(tmp_fname); /* Remember to open this on the NULL context. We need * it to stay around after we return from here. */ tmp_db = db_open(NULL, tmp_fname, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600); if (tmp_db == NULL) { DEBUG(0, ("tdbsam_convert_backup: Failed to create backup TDB passwd " "[%s]\n", tmp_fname)); TALLOC_FREE(frame); return false; } if (orig_db->transaction_start(orig_db) != 0) { DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (1)\n")); unlink(tmp_fname); TALLOC_FREE(tmp_db); TALLOC_FREE(frame); return false; } if (tmp_db->transaction_start(tmp_db) != 0) { DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (2)\n")); orig_db->transaction_cancel(orig_db); unlink(tmp_fname); TALLOC_FREE(tmp_db); TALLOC_FREE(frame); return false; } bs.new_db = tmp_db; bs.success = true; ret = orig_db->traverse(orig_db, backup_copy_fn, (void *)&bs); if (ret < 0) { DEBUG(0, ("tdbsam_convert_backup: traverse failed\n")); goto cancel; } if (!bs.success) { DEBUG(0, ("tdbsam_convert_backup: Rewriting records failed\n")); goto cancel; } if (orig_db->transaction_commit(orig_db) != 0) { smb_panic("tdbsam_convert_backup: orig commit failed\n"); } if (tmp_db->transaction_commit(tmp_db) != 0) { smb_panic("tdbsam_convert_backup: orig commit failed\n"); } /* be sure to close the DBs _before_ renaming the file */ TALLOC_FREE(orig_db); TALLOC_FREE(tmp_db); /* This is safe from other users as we know we're * under a mutex here. */ if (rename(tmp_fname, dbname) == -1) { DEBUG(0, ("tdbsam_convert_backup: rename of %s to %s failed %s\n", tmp_fname, dbname, strerror(errno))); smb_panic("tdbsam_convert_backup: replace passdb failed\n"); } TALLOC_FREE(frame); /* re-open the converted TDB */ orig_db = db_open(NULL, dbname, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600); if (orig_db == NULL) { DEBUG(0, ("tdbsam_convert_backup: Failed to re-open " "converted passdb TDB [%s]\n", dbname)); return false; } DEBUG(1, ("tdbsam_convert_backup: updated %s file.\n", dbname )); /* Replace the global db pointer. */ *pp_db = orig_db; return true; cancel: if (orig_db->transaction_cancel(orig_db) != 0) { smb_panic("tdbsam_convert: transaction_cancel failed"); } if (tmp_db->transaction_cancel(tmp_db) != 0) { smb_panic("tdbsam_convert: transaction_cancel failed"); } unlink(tmp_fname); TALLOC_FREE(tmp_db); TALLOC_FREE(frame); return false; }
NTSTATUS cli_dfs_get_referral(TALLOC_CTX *ctx, struct cli_state *cli, const char *path, struct client_dfs_referral **refs, size_t *num_refs, size_t *consumed) { unsigned int param_len = 0; uint16_t recv_flags2; uint8_t *param = NULL; uint8_t *rdata = NULL; char *p; char *endp; smb_ucs2_t *path_ucs; char *consumed_path = NULL; uint16_t consumed_ucs; uint16_t num_referrals; struct client_dfs_referral *referrals = NULL; NTSTATUS status; TALLOC_CTX *frame = talloc_stackframe(); *num_refs = 0; *refs = NULL; param = talloc_array(talloc_tos(), uint8_t, 2); if (!param) { status = NT_STATUS_NO_MEMORY; goto out; } SSVAL(param, 0, 0x03); /* max referral level */ param = trans2_bytes_push_str(param, smbXcli_conn_use_unicode(cli->conn), path, strlen(path)+1, NULL); if (!param) { status = NT_STATUS_NO_MEMORY; goto out; } param_len = talloc_get_size(param); path_ucs = (smb_ucs2_t *)¶m[2]; if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { DATA_BLOB in_input_buffer; DATA_BLOB in_output_buffer = data_blob_null; DATA_BLOB out_input_buffer = data_blob_null; DATA_BLOB out_output_buffer = data_blob_null; in_input_buffer.data = param; in_input_buffer.length = param_len; status = smb2cli_ioctl(cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon, UINT64_MAX, /* in_fid_persistent */ UINT64_MAX, /* in_fid_volatile */ FSCTL_DFS_GET_REFERRALS, 0, /* in_max_input_length */ &in_input_buffer, CLI_BUFFER_SIZE, /* in_max_output_length */ &in_output_buffer, SMB2_IOCTL_FLAG_IS_FSCTL, talloc_tos(), &out_input_buffer, &out_output_buffer); if (!NT_STATUS_IS_OK(status)) { goto out; } if (out_output_buffer.length < 4) { status = NT_STATUS_INVALID_NETWORK_RESPONSE; goto out; } recv_flags2 = FLAGS2_UNICODE_STRINGS; rdata = out_output_buffer.data; endp = (char *)rdata + out_output_buffer.length; } else { unsigned int data_len = 0; uint16_t setup[1]; SSVAL(setup, 0, TRANSACT2_GET_DFS_REFERRAL); status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, 0xffff, 0, 0, setup, 1, 0, param, param_len, 2, NULL, 0, CLI_BUFFER_SIZE, &recv_flags2, NULL, 0, NULL, /* rsetup */ NULL, 0, NULL, &rdata, 4, &data_len); if (!NT_STATUS_IS_OK(status)) { goto out; } endp = (char *)rdata + data_len; } consumed_ucs = SVAL(rdata, 0); num_referrals = SVAL(rdata, 2); /* consumed_ucs is the number of bytes * of the UCS2 path consumed not counting any * terminating null. We need to convert * back to unix charset and count again * to get the number of bytes consumed from * the incoming path. */ errno = 0; if (pull_string_talloc(talloc_tos(), NULL, 0, &consumed_path, path_ucs, consumed_ucs, STR_UNICODE) == 0) { if (errno != 0) { status = map_nt_error_from_unix(errno); } else { status = NT_STATUS_INVALID_NETWORK_RESPONSE; } goto out; } if (consumed_path == NULL) { status = map_nt_error_from_unix(errno); goto out; } *consumed = strlen(consumed_path); if (num_referrals != 0) { uint16_t ref_version; uint16_t ref_size; int i; uint16_t node_offset; referrals = talloc_array(ctx, struct client_dfs_referral, num_referrals); if (!referrals) { status = NT_STATUS_NO_MEMORY; goto out; } /* start at the referrals array */ p = (char *)rdata+8; for (i=0; i<num_referrals && p < endp; i++) { if (p + 18 > endp) { goto out; } ref_version = SVAL(p, 0); ref_size = SVAL(p, 2); node_offset = SVAL(p, 16); if (ref_version != 3) { p += ref_size; continue; } referrals[i].proximity = SVAL(p, 8); referrals[i].ttl = SVAL(p, 10); if (p + node_offset > endp) { status = NT_STATUS_INVALID_NETWORK_RESPONSE; goto out; } clistr_pull_talloc(referrals, (const char *)rdata, recv_flags2, &referrals[i].dfspath, p+node_offset, PTR_DIFF(endp, p+node_offset), STR_TERMINATE|STR_UNICODE); if (!referrals[i].dfspath) { status = map_nt_error_from_unix(errno); goto out; } p += ref_size; } if (i < num_referrals) { status = NT_STATUS_INVALID_NETWORK_RESPONSE; goto out; } }
static bool parse_ace(SEC_ACE *ace, const char *orig_str) { char *p; const char *cp; char *tok; unsigned int atype = 0; unsigned int aflags = 0; unsigned int amask = 0; DOM_SID sid; SEC_ACCESS mask; const struct perm_value *v; char *str = SMB_STRDUP(orig_str); TALLOC_CTX *frame = talloc_stackframe(); if (!str) { TALLOC_FREE(frame); return False; } ZERO_STRUCTP(ace); p = strchr_m(str,':'); if (!p) { printf("ACE '%s': missing ':'.\n", orig_str); SAFE_FREE(str); TALLOC_FREE(frame); return False; } *p = '\0'; p++; /* Try to parse numeric form */ if (sscanf(p, "%i/%i/%i", &atype, &aflags, &amask) == 3 && string_to_sid(&sid, str)) { goto done; } /* Try to parse text form */ if (!string_to_sid(&sid, str)) { printf("ACE '%s': failed to convert '%s' to SID\n", orig_str, str); SAFE_FREE(str); TALLOC_FREE(frame); return False; } cp = p; if (!next_token_talloc(frame, &cp, &tok, "/")) { printf("ACE '%s': failed to find '/' character.\n", orig_str); SAFE_FREE(str); TALLOC_FREE(frame); return False; } if (strncmp(tok, "ALLOWED", strlen("ALLOWED")) == 0) { atype = SEC_ACE_TYPE_ACCESS_ALLOWED; } else if (strncmp(tok, "DENIED", strlen("DENIED")) == 0) { atype = SEC_ACE_TYPE_ACCESS_DENIED; } else { printf("ACE '%s': missing 'ALLOWED' or 'DENIED' entry at '%s'\n", orig_str, tok); SAFE_FREE(str); TALLOC_FREE(frame); return False; } /* Only numeric form accepted for flags at present */ /* no flags on share permissions */ if (!(next_token_talloc(frame, &cp, &tok, "/") && sscanf(tok, "%i", &aflags) && aflags == 0)) { printf("ACE '%s': bad integer flags entry at '%s'\n", orig_str, tok); SAFE_FREE(str); TALLOC_FREE(frame); return False; } if (!next_token_talloc(frame, &cp, &tok, "/")) { printf("ACE '%s': missing / at '%s'\n", orig_str, tok); SAFE_FREE(str); TALLOC_FREE(frame); return False; } if (strncmp(tok, "0x", 2) == 0) { if (sscanf(tok, "%i", &amask) != 1) { printf("ACE '%s': bad hex number at '%s'\n", orig_str, tok); TALLOC_FREE(frame); SAFE_FREE(str); return False; } goto done; } for (v = standard_values; v->perm; v++) { if (strcmp(tok, v->perm) == 0) { amask = v->mask; goto done; } } p = tok; while(*p) { bool found = False; for (v = special_values; v->perm; v++) { if (v->perm[0] == *p) { amask |= v->mask; found = True; } } if (!found) { printf("ACE '%s': bad permission value at '%s'\n", orig_str, p); TALLOC_FREE(frame); SAFE_FREE(str); return False; } p++; } if (*p) { TALLOC_FREE(frame); SAFE_FREE(str); return False; } done: mask = amask; init_sec_ace(ace, &sid, atype, mask, aflags); SAFE_FREE(str); TALLOC_FREE(frame); return True; }
int SMBC_close_ctx(SMBCCTX *context, SMBCFILE *file) { SMBCSRV *srv; char *server = NULL, *share = NULL, *user = NULL, *password = NULL; char *path = NULL; char *targetpath = NULL; uint16_t port = 0; struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; } /* IS a dir ... */ if (!file->file) { TALLOC_FREE(frame); return smbc_getFunctionClosedir(context)(context, file); } /*d_printf(">>>close: parsing %s\n", file->fname);*/ if (SMBC_parse_path(frame, context, file->fname, NULL, &server, &port, &share, &path, &user, &password, NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } /*d_printf(">>>close: resolving %s\n", path);*/ status = cli_resolve_path(frame, "", context->internal->auth_info, file->srv->cli, path, &targetcli, &targetpath); if (!NT_STATUS_IS_OK(status)) { d_printf("Could not resolve %s\n", path); errno = ENOENT; TALLOC_FREE(frame); return -1; } /*d_printf(">>>close: resolved path as %s\n", targetpath);*/ if (!NT_STATUS_IS_OK(cli_close(targetcli, file->cli_fd))) { DEBUG(3, ("cli_close failed on %s. purging server.\n", file->fname)); /* Deallocate slot and remove the server * from the server cache if unused */ errno = SMBC_errno(context, targetcli); srv = file->srv; DLIST_REMOVE(context->internal->files, file); SAFE_FREE(file->fname); SAFE_FREE(file); smbc_getFunctionRemoveUnusedServer(context)(context, srv); TALLOC_FREE(frame); return -1; } DLIST_REMOVE(context->internal->files, file); SAFE_FREE(file->fname); SAFE_FREE(file); TALLOC_FREE(frame); return 0; }
int main(int argc, const char *argv[]) { int opt; int retval = 0; enum acl_mode mode = SMB_ACL_SET; static char *the_acl = NULL; fstring sharename; bool force_acl = False; int snum; poptContext pc; bool initialize_sid = False; struct poptOption long_options[] = { POPT_AUTOHELP { "remove", 'r', POPT_ARG_STRING, &the_acl, 'r', "Delete an ACE", "ACL" }, { "modify", 'm', POPT_ARG_STRING, &the_acl, 'm', "Modify an acl", "ACL" }, { "add", 'a', POPT_ARG_STRING, &the_acl, 'a', "Add an ACE", "ACL" }, { "replace", 'R', POPT_ARG_STRING, &the_acl, 'R', "Set share mission ACL", "ACLS" }, { "view", 'v', POPT_ARG_NONE, NULL, 'v', "View current share permissions" }, { "machine-sid", 'M', POPT_ARG_NONE, NULL, 'M', "Initialize the machine SID" }, { "force", 'F', POPT_ARG_NONE, NULL, 'F', "Force storing the ACL", "ACLS" }, POPT_COMMON_SAMBA { NULL } }; if ( !(ctx = talloc_stackframe()) ) { fprintf( stderr, "Failed to initialize talloc context!\n"); return -1; } /* set default debug level to 1 regardless of what smb.conf sets */ setup_logging( "sharesec", True ); DEBUGLEVEL_CLASS[DBGC_ALL] = 1; dbf = x_stderr; x_setbuf( x_stderr, NULL ); pc = poptGetContext("sharesec", argc, argv, long_options, 0); poptSetOtherOptionHelp(pc, "sharename\n"); while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case 'r': the_acl = smb_xstrdup(poptGetOptArg(pc)); mode = SMB_ACL_DELETE; break; case 'm': the_acl = smb_xstrdup(poptGetOptArg(pc)); mode = SMB_ACL_MODIFY; break; case 'a': the_acl = smb_xstrdup(poptGetOptArg(pc)); mode = SMB_ACL_ADD; break; case 'R': the_acl = smb_xstrdup(poptGetOptArg(pc)); mode = SMB_ACL_SET; break; case 'v': mode = SMB_ACL_VIEW; break; case 'F': force_acl = True; break; case 'M': initialize_sid = True; break; } } setlinebuf(stdout); load_case_tables(); lp_load( get_dyn_CONFIGFILE(), False, False, False, True ); /* check for initializing secrets.tdb first */ if ( initialize_sid ) { DOM_SID *sid = get_global_sam_sid(); if ( !sid ) { fprintf( stderr, "Failed to retrieve Machine SID!\n"); return 3; } printf ("%s\n", sid_string_tos( sid ) ); return 0; } if ( mode == SMB_ACL_VIEW && force_acl ) { fprintf( stderr, "Invalid combination of -F and -v\n"); return -1; } /* get the sharename */ if(!poptPeekArg(pc)) { poptPrintUsage(pc, stderr, 0); return -1; } fstrcpy(sharename, poptGetArg(pc)); snum = lp_servicenumber( sharename ); if ( snum == -1 && !force_acl ) { fprintf( stderr, "Invalid sharename: %s\n", sharename); return -1; } retval = change_share_sec(ctx, sharename, the_acl, mode); talloc_destroy(ctx); return retval; }
/* * Get info from an SMB server on a file. Use a qpathinfo call first * and if that fails, use getatr, as Win95 sometimes refuses qpathinfo */ bool SMBC_getatr(SMBCCTX * context, SMBCSRV *srv, const char *path, uint16_t *mode, off_t *size, struct timespec *create_time_ts, struct timespec *access_time_ts, struct timespec *write_time_ts, struct timespec *change_time_ts, SMB_INO_T *ino) { char *fixedpath = NULL; char *targetpath = NULL; struct cli_state *targetcli = NULL; time_t write_time; TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return False; } /* path fixup for . and .. */ if (strequal(path, ".") || strequal(path, "..")) { fixedpath = talloc_strdup(frame, "\\"); if (!fixedpath) { errno = ENOMEM; TALLOC_FREE(frame); return False; } } else { fixedpath = talloc_strdup(frame, path); if (!fixedpath) { errno = ENOMEM; TALLOC_FREE(frame); return False; } trim_string(fixedpath, NULL, "\\.."); trim_string(fixedpath, NULL, "\\."); } DEBUG(4,("SMBC_getatr: sending qpathinfo\n")); status = cli_resolve_path(frame, "", context->internal->auth_info, srv->cli, fixedpath, &targetcli, &targetpath); if (!NT_STATUS_IS_OK(status)) { d_printf("Couldn't resolve %s\n", path); errno = ENOENT; TALLOC_FREE(frame); return False; } if (!srv->no_pathinfo2 && NT_STATUS_IS_OK(cli_qpathinfo2(targetcli, targetpath, create_time_ts, access_time_ts, write_time_ts, change_time_ts, size, mode, ino))) { TALLOC_FREE(frame); return True; } srv->no_pathinfo2 = True; if (!srv->no_pathinfo3 && NT_STATUS_IS_OK(cli_qpathinfo3(targetcli, targetpath, create_time_ts, access_time_ts, write_time_ts, change_time_ts, size, mode, ino))) { TALLOC_FREE(frame); return True; } srv->no_pathinfo3 = True; /* if this is NT then don't bother with the getatr */ if (smb1cli_conn_capabilities(targetcli->conn) & CAP_NT_SMBS) { goto all_failed; } if (NT_STATUS_IS_OK(cli_getatr(targetcli, targetpath, mode, size, &write_time))) { struct timespec w_time_ts; w_time_ts = convert_time_t_to_timespec(write_time); if (write_time_ts != NULL) { *write_time_ts = w_time_ts; } if (create_time_ts != NULL) { *create_time_ts = w_time_ts; } if (access_time_ts != NULL) { *access_time_ts = w_time_ts; } if (change_time_ts != NULL) { *change_time_ts = w_time_ts; } if (ino) { *ino = 0; } TALLOC_FREE(frame); return True; } all_failed: srv->no_pathinfo2 = False; srv->no_pathinfo3 = False; errno = EPERM; TALLOC_FREE(frame); return False; }
int main(int argc, const char **argv) { struct tevent_context *evt_ctx; struct messaging_context *msg_ctx; struct db_context *db; uint16_t count; const char *dbname; const char *opname; enum dbwrap_op op; const char *keyname = ""; const char *keytype = "int32"; enum dbwrap_type type; const char *valuestr = "0"; int persistent = 0; int non_persistent = 0; int tdb_flags = TDB_DEFAULT; TALLOC_CTX *mem_ctx = talloc_stackframe(); int ret = 1; struct poptOption popt_options[] = { POPT_AUTOHELP POPT_COMMON_SAMBA { "non-persistent", 0, POPT_ARG_NONE, &non_persistent, 0, "treat the database as non-persistent " "(CAVEAT: This mode might wipe your database!)", NULL }, { "persistent", 0, POPT_ARG_NONE, &persistent, 0, "treat the database as persistent", NULL }, POPT_TABLEEND }; int opt; const char **extra_argv; int extra_argc = 0; poptContext pc; smb_init_locale(); lp_set_cmdline("log level", "0"); setup_logging(argv[0], DEBUG_STDERR); pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST); while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { default: fprintf(stderr, "Invalid option %s: %s\n", poptBadOption(pc, 0), poptStrerror(opt)); goto done; } } /* setup the remaining options for the main program to use */ extra_argv = poptGetArgs(pc); if (extra_argv) { extra_argv++; while (extra_argv[extra_argc]) extra_argc++; } lp_load_global(get_dyn_CONFIGFILE()); if ((extra_argc < 2) || (extra_argc > 5)) { d_fprintf(stderr, "USAGE: %s [options] <database> <op> [<key> [<type> " "[<value>]]]\n" " ops: fetch, store, delete, exists, " "erase, listkeys, listwatchers\n" " types: int32, uint32, string, hex\n", argv[0]); goto done; } if ((persistent == 0 && non_persistent == 0) || (persistent == 1 && non_persistent == 1)) { d_fprintf(stderr, "ERROR: you must specify exactly one " "of --persistent and --non-persistent\n"); goto done; } else if (non_persistent == 1) { tdb_flags |= TDB_CLEAR_IF_FIRST; } dbname = extra_argv[0]; opname = extra_argv[1]; if (strcmp(opname, "store") == 0) { if (extra_argc != 5) { d_fprintf(stderr, "ERROR: operation 'store' requires " "value argument\n"); goto done; } valuestr = extra_argv[4]; keytype = extra_argv[3]; keyname = extra_argv[2]; op = OP_STORE; } else if (strcmp(opname, "fetch") == 0) { if (extra_argc != 4) { d_fprintf(stderr, "ERROR: operation 'fetch' requires " "type but not value argument\n"); goto done; } op = OP_FETCH; keytype = extra_argv[3]; keyname = extra_argv[2]; } else if (strcmp(opname, "delete") == 0) { if (extra_argc != 3) { d_fprintf(stderr, "ERROR: operation 'delete' does " "not allow type nor value argument\n"); goto done; } keyname = extra_argv[2]; op = OP_DELETE; } else if (strcmp(opname, "erase") == 0) { if (extra_argc != 2) { d_fprintf(stderr, "ERROR: operation 'erase' does " "not take a key argument\n"); goto done; } op = OP_ERASE; } else if (strcmp(opname, "listkeys") == 0) { if (extra_argc != 2) { d_fprintf(stderr, "ERROR: operation 'listkeys' does " "not take a key argument\n"); goto done; } op = OP_LISTKEYS; } else if (strcmp(opname, "exists") == 0) { if (extra_argc != 3) { d_fprintf(stderr, "ERROR: operation 'exists' does " "not allow type nor value argument\n"); goto done; } keyname = extra_argv[2]; op = OP_EXISTS; keytype = "string"; } else { d_fprintf(stderr, "ERROR: invalid op '%s' specified\n" " supported ops: fetch, store, delete, exists, " "erase, listkeys, listwatchers\n", opname); goto done; } if (strcmp(keytype, "int32") == 0) { type = TYPE_INT32; } else if (strcmp(keytype, "uint32") == 0) { type = TYPE_UINT32; } else if (strcmp(keytype, "string") == 0) { type = TYPE_STRING; } else if (strcmp(keytype, "hex") == 0) { type = TYPE_HEX; } else if (strcmp(keytype, "none") == 0) { type = TYPE_NONE; } else { d_fprintf(stderr, "ERROR: invalid type '%s' specified.\n" " supported types: int32, uint32, " "string, hex, none\n", keytype); goto done; } evt_ctx = samba_tevent_context_init(mem_ctx); if (evt_ctx == NULL) { d_fprintf(stderr, "ERROR: could not init event context\n"); goto done; } msg_ctx = messaging_init(mem_ctx, evt_ctx); if (msg_ctx == NULL) { d_fprintf(stderr, "ERROR: could not init messaging context\n"); goto done; } switch (op) { case OP_FETCH: case OP_STORE: case OP_DELETE: case OP_ERASE: case OP_LISTKEYS: case OP_EXISTS: db = db_open(mem_ctx, dbname, 0, tdb_flags, O_RDWR | O_CREAT, 0644, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (db == NULL) { d_fprintf(stderr, "ERROR: could not open dbname\n"); goto done; } break; default: db = NULL; break; } for (count = 0; dispatch_table[count].cmd != NULL; count++) { if ((op == dispatch_table[count].op) && (type == dispatch_table[count].type)) { ret = dispatch_table[count].cmd(db, keyname, valuestr); break; } } done: TALLOC_FREE(mem_ctx); return ret; }
/* * Set file info on an SMB server. Use setpathinfo call first. If that * fails, use setattrE.. * * Access and modification time parameters are always used and must be * provided. Create time, if zero, will be determined from the actual create * time of the file. If non-zero, the create time will be set as well. * * "mode" (attributes) parameter may be set to -1 if it is not to be set. */ bool SMBC_setatr(SMBCCTX * context, SMBCSRV *srv, char *path, time_t create_time, time_t access_time, time_t write_time, time_t change_time, uint16_t mode) { uint16_t fd; int ret; TALLOC_CTX *frame = talloc_stackframe(); /* * First, try setpathinfo (if qpathinfo succeeded), for it is the * modern function for "new code" to be using, and it works given a * filename rather than requiring that the file be opened to have its * attributes manipulated. */ if (srv->no_pathinfo || !NT_STATUS_IS_OK(cli_setpathinfo_basic(srv->cli, path, create_time, access_time, write_time, change_time, mode))) { /* * setpathinfo is not supported; go to plan B. * * cli_setatr() does not work on win98, and it also doesn't * support setting the access time (only the modification * time), so in all cases, we open the specified file and use * cli_setattrE() which should work on all OS versions, and * supports both times. */ /* Don't try {q,set}pathinfo() again, with this server */ srv->no_pathinfo = True; /* Open the file */ if (!NT_STATUS_IS_OK(cli_open(srv->cli, path, O_RDWR, DENY_NONE, &fd))) { errno = SMBC_errno(context, srv->cli); TALLOC_FREE(frame); return -1; } /* Set the new attributes */ ret = NT_STATUS_IS_OK(cli_setattrE(srv->cli, fd, change_time, access_time, write_time)); /* Close the file */ cli_close(srv->cli, fd); /* * Unfortunately, setattrE() doesn't have a provision for * setting the access mode (attributes). We'll have to try * cli_setatr() for that, and with only this parameter, it * seems to work on win98. */ if (ret && mode != (uint16_t) -1) { ret = NT_STATUS_IS_OK(cli_setatr(srv->cli, path, mode, 0)); } if (! ret) { errno = SMBC_errno(context, srv->cli); TALLOC_FREE(frame); return False; } } TALLOC_FREE(frame); return True; }
static sbcErr smbconf_reg_get_includes_internal(TALLOC_CTX *mem_ctx, struct registry_key *key, uint32_t *num_includes, char ***includes) { WERROR werr; sbcErr err; uint32_t count; struct registry_value *value = NULL; char **tmp_includes = NULL; const char **array = NULL; TALLOC_CTX *tmp_ctx = talloc_stackframe(); if (!smbconf_value_exists(key, INCLUDES_VALNAME)) { /* no includes */ *num_includes = 0; *includes = NULL; err = SBC_ERR_OK; goto done; } werr = reg_queryvalue(tmp_ctx, key, INCLUDES_VALNAME, &value); if (!W_ERROR_IS_OK(werr)) { err = SBC_ERR_ACCESS_DENIED; goto done; } if (value->type != REG_MULTI_SZ) { /* wrong type -- ignore */ err = SBC_ERR_OK; goto done; } if (!pull_reg_multi_sz(tmp_ctx, &value->data, &array)) { err = SBC_ERR_NOMEM; goto done; } for (count = 0; array[count] != NULL; count++) { err = smbconf_add_string_to_array(tmp_ctx, &tmp_includes, count, array[count]); if (!SBC_ERROR_IS_OK(err)) { goto done; } } if (count > 0) { *includes = talloc_move(mem_ctx, &tmp_includes); if (*includes == NULL) { err = SBC_ERR_NOMEM; goto done; } *num_includes = count; } else { *num_includes = 0; *includes = NULL; } err = SBC_ERR_OK; done: talloc_free(tmp_ctx); return err; }
off_t SMBC_lseek_ctx(SMBCCTX *context, SMBCFILE *file, off_t offset, int whence) { off_t size; char *server = NULL, *share = NULL, *user = NULL, *password = NULL; char *path = NULL; char *targetpath = NULL; struct cli_state *targetcli = NULL; uint16_t port = 0; TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; } if (!file->file) { errno = EINVAL; TALLOC_FREE(frame); return -1; /* Can't lseek a dir ... */ } switch (whence) { case SEEK_SET: file->offset = offset; break; case SEEK_CUR: file->offset += offset; break; case SEEK_END: /*d_printf(">>>lseek: parsing %s\n", file->fname);*/ if (SMBC_parse_path(frame, context, file->fname, NULL, &server, &port, &share, &path, &user, &password, NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } /*d_printf(">>>lseek: resolving %s\n", path);*/ status = cli_resolve_path( frame, "", context->internal->auth_info, file->srv->cli, path, &targetcli, &targetpath); if (!NT_STATUS_IS_OK(status)) { d_printf("Could not resolve %s\n", path); errno = ENOENT; TALLOC_FREE(frame); return -1; } /*d_printf(">>>lseek: resolved path as %s\n", targetpath);*/ if (!NT_STATUS_IS_OK(cli_qfileinfo_basic( targetcli, file->cli_fd, NULL, &size, NULL, NULL, NULL, NULL, NULL))) { off_t b_size = size; if (!NT_STATUS_IS_OK(cli_getattrE(targetcli, file->cli_fd, NULL, &b_size, NULL, NULL, NULL))) { errno = EINVAL; TALLOC_FREE(frame); return -1; } else size = b_size; } file->offset = size + offset; break; default: errno = EINVAL; break; } TALLOC_FREE(frame); return file->offset; }
/** * get the list of share names defined in the configuration. * registry version. */ static sbcErr smbconf_reg_get_share_names(struct smbconf_ctx *ctx, TALLOC_CTX *mem_ctx, uint32_t *num_shares, char ***share_names) { uint32_t count; uint32_t added_count = 0; TALLOC_CTX *tmp_ctx = NULL; WERROR werr; sbcErr err = SBC_ERR_OK; char *subkey_name = NULL; char **tmp_share_names = NULL; if ((num_shares == NULL) || (share_names == NULL)) { return SBC_ERR_INVALID_PARAM; } tmp_ctx = talloc_stackframe(); /* if there are values in the base key, return NULL as share name */ if (smbconf_reg_key_has_values(rpd(ctx)->base_key)) { err = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names, 0, NULL); if (!SBC_ERROR_IS_OK(err)) { goto done; } added_count++; } /* make sure "global" is always listed first */ if (smbconf_share_exists(ctx, GLOBAL_NAME)) { err = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names, added_count, GLOBAL_NAME); if (!SBC_ERROR_IS_OK(err)) { goto done; } added_count++; } for (count = 0; werr = reg_enumkey(tmp_ctx, rpd(ctx)->base_key, count, &subkey_name, NULL), W_ERROR_IS_OK(werr); count++) { if (strequal(subkey_name, GLOBAL_NAME)) { continue; } err = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names, added_count, subkey_name); if (!SBC_ERROR_IS_OK(err)) { goto done; } added_count++; } if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) { err = SBC_ERR_NO_MORE_ITEMS; goto done; } err = SBC_ERR_OK; *num_shares = added_count; if (added_count > 0) { *share_names = talloc_move(mem_ctx, &tmp_share_names); } else { *share_names = NULL; } done: talloc_free(tmp_ctx); return err; }
int SMBC_ftruncate_ctx(SMBCCTX *context, SMBCFILE *file, off_t length) { off_t size = length; char *server = NULL; char *share = NULL; char *user = NULL; char *password = NULL; char *path = NULL; char *targetpath = NULL; uint16_t port = 0; struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; } if (!file->file) { errno = EINVAL; TALLOC_FREE(frame); return -1; } /*d_printf(">>>fstat: parsing %s\n", file->fname);*/ if (SMBC_parse_path(frame, context, file->fname, NULL, &server, &port, &share, &path, &user, &password, NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } /*d_printf(">>>fstat: resolving %s\n", path);*/ status = cli_resolve_path(frame, "", context->internal->auth_info, file->srv->cli, path, &targetcli, &targetpath); if (!NT_STATUS_IS_OK(status)) { d_printf("Could not resolve %s\n", path); errno = ENOENT; TALLOC_FREE(frame); return -1; } /*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/ if (!NT_STATUS_IS_OK(cli_ftruncate(targetcli, file->cli_fd, (uint64_t)size))) { errno = EINVAL; TALLOC_FREE(frame); return -1; } TALLOC_FREE(frame); return 0; }
bool cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32_t stype, void (*fn)(const char *, uint32_t, const char *, void *), void *state) { char *rparam = NULL; char *rdata = NULL; char *rdata_end = NULL; unsigned int rdrcnt,rprcnt; char *p; char param[1024]; int uLevel = 1; size_t len; uint32_t func = RAP_NetServerEnum2; char *last_entry = NULL; int total_cnt = 0; int return_cnt = 0; int res; errno = 0; /* reset */ /* * This may take more than one transaction, so we should loop until * we no longer get a more data to process or we have all of the * items. */ do { /* send a SMBtrans command with api NetServerEnum */ p = param; SIVAL(p,0,func); /* api number */ p += 2; if (func == RAP_NetServerEnum3) { strlcpy(p,"WrLehDzz", sizeof(param)-PTR_DIFF(p,param)); } else { strlcpy(p,"WrLehDz", sizeof(param)-PTR_DIFF(p,param)); } p = skip_string(param, sizeof(param), p); strlcpy(p,"B16BBDz", sizeof(param)-PTR_DIFF(p,param)); p = skip_string(param, sizeof(param), p); SSVAL(p,0,uLevel); SSVAL(p,2,CLI_BUFFER_SIZE); p += 4; SIVAL(p,0,stype); p += 4; /* If we have more data, tell the server where * to continue from. */ len = push_ascii(p, workgroup, sizeof(param) - PTR_DIFF(p,param) - 1, STR_TERMINATE|STR_UPPER); if (len == 0) { SAFE_FREE(last_entry); return false; } p += len; if (func == RAP_NetServerEnum3) { len = push_ascii(p, last_entry ? last_entry : "", sizeof(param) - PTR_DIFF(p,param) - 1, STR_TERMINATE); if (len == 0) { SAFE_FREE(last_entry); return false; } p += len; } /* Next time through we need to use the continue api */ func = RAP_NetServerEnum3; if (!cli_api(cli, param, PTR_DIFF(p,param), 8, /* params, length, max */ NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */ &rparam, &rprcnt, /* return params, return size */ &rdata, &rdrcnt)) { /* return data, return size */ /* break out of the loop on error */ res = -1; break; } rdata_end = rdata + rdrcnt; res = rparam ? SVAL(rparam,0) : -1; if (res == 0 || res == ERRmoredata || (res != -1 && cli_errno(cli) == 0)) { char *sname = NULL; int i, count; int converter=SVAL(rparam,2); /* Get the number of items returned in this buffer */ count = SVAL(rparam, 4); /* The next field contains the number of items left, * including those returned in this buffer. So the * first time through this should contain all of the * entries. */ if (total_cnt == 0) { total_cnt = SVAL(rparam, 6); } /* Keep track of how many we have read */ return_cnt += count; p = rdata; /* The last name in the previous NetServerEnum reply is * sent back to server in the NetServerEnum3 request * (last_entry). The next reply should repeat this entry * as the first element. We have no proof that this is * always true, but from traces that seems to be the * behavior from Window Servers. So first lets do a lot * of checking, just being paranoid. If the string * matches then we already saw this entry so skip it. * * NOTE: sv1_name field must be null terminated and has * a max size of 16 (NetBIOS Name). */ if (last_entry && count && p && (strncmp(last_entry, p, 16) == 0)) { count -= 1; /* Skip this entry */ return_cnt = -1; /* Not part of total, so don't count. */ p = rdata + 26; /* Skip the whole record */ } for (i = 0; i < count; i++, p += 26) { int comment_offset; const char *cmnt; const char *p1; char *s1, *s2; TALLOC_CTX *frame = talloc_stackframe(); uint32_t entry_stype; if (p + 26 > rdata_end) { TALLOC_FREE(frame); break; } sname = p; comment_offset = (IVAL(p,22) & 0xFFFF)-converter; cmnt = comment_offset?(rdata+comment_offset):""; if (comment_offset < 0 || comment_offset >= (int)rdrcnt) { TALLOC_FREE(frame); continue; } /* Work out the comment length. */ for (p1 = cmnt, len = 0; *p1 && p1 < rdata_end; len++) p1++; if (!*p1) { len++; } entry_stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY; pull_string_talloc(frame,rdata,0, &s1,sname,16,STR_ASCII); pull_string_talloc(frame,rdata,0, &s2,cmnt,len,STR_ASCII); if (!s1 || !s2) { TALLOC_FREE(frame); continue; } fn(s1, entry_stype, s2, state); TALLOC_FREE(frame); } /* We are done with the old last entry, so now we can free it */ if (last_entry) { SAFE_FREE(last_entry); /* This will set it to null */ } /* We always make a copy of the last entry if we have one */ if (sname) { last_entry = smb_xstrdup(sname); } /* If we have more data, but no last entry then error out */ if (!last_entry && (res == ERRmoredata)) { errno = EINVAL; res = 0; } } SAFE_FREE(rparam); SAFE_FREE(rdata); } while ((res == ERRmoredata) && (total_cnt > return_cnt)); SAFE_FREE(rparam); SAFE_FREE(rdata); SAFE_FREE(last_entry); if (res == -1) { errno = cli_errno(cli); } else { if (!return_cnt) { /* this is a very special case, when the domain master for the work group isn't part of the work group itself, there is something wild going on */ errno = ENOENT; } } return(return_cnt > 0); }
static bool fdpass2_child(int ready_fd) { struct tevent_context *ev = NULL; struct messaging_context *msg_ctx = NULL; TALLOC_CTX *frame = talloc_stackframe(); bool retval = false; uint8_t c = 1; struct tevent_req *subreq; int ret; ssize_t bytes; int up_fd, down_fd; struct messaging_rec *rec; bool ok; ev = samba_tevent_context_init(frame); if (ev == NULL) { fprintf(stderr, "child: tevent_context_init failed\n"); goto done; } msg_ctx = messaging_init(ev, ev); if (msg_ctx == NULL) { fprintf(stderr, "child: messaging_init failed\n"); goto done; } /* Tell the parent we are ready to receive mesages. */ bytes = write(ready_fd, &c, 1); if (bytes != 1) { perror("child: failed to write to ready_fd"); goto done; } subreq = messaging_filtered_read_send(frame, /* TALLOC_CTX */ ev, msg_ctx, fdpass2_filter, NULL); if (subreq == NULL) { fprintf(stderr, "child: messaging_filtered_read_send failed\n"); goto done; } ok = tevent_req_poll(subreq, ev); if (!ok) { fprintf(stderr, "child: tevent_req_poll failed\n"); goto done; } ret = messaging_filtered_read_recv(subreq, frame, &rec); TALLOC_FREE(subreq); if (ret != 0) { fprintf(stderr, "child: messaging_filtered_read_recv failed\n"); goto done; } SMB_ASSERT(rec->num_fds == 2); /* Tell the parent we are done. */ bytes = write(ready_fd, &c, 1); if (bytes != 1) { perror("child: failed to write to ready_fd"); goto done; } up_fd = rec->fds[0]; down_fd = rec->fds[1]; bytes = read(up_fd, &c, 1); if (bytes != 1) { perror("child: read from up_fd failed"); goto done; } bytes = write(down_fd, &c, 1); if (bytes != 1) { perror("child: write to down_fd failed"); } printf("child: done\n"); retval = true; done: TALLOC_FREE(frame); return retval; }
/* show the current server status */ void status_page(void) { const char *v; int autorefresh=0; int refresh_interval=30; int nr_running=0; bool waitup = False; TALLOC_CTX *ctx = talloc_stackframe(); const char form_name[] = "status"; smbd_pid = pid_to_procid(pidfile_pid("smbd")); if (!verify_xsrf_token(form_name)) { goto output_page; } if (cgi_variable("smbd_restart") || cgi_variable("all_restart")) { stop_smbd(); start_smbd(); waitup=True; } if (cgi_variable("smbd_start") || cgi_variable("all_start")) { start_smbd(); waitup=True; } if (cgi_variable("smbd_stop") || cgi_variable("all_stop")) { stop_smbd(); waitup=True; } if (cgi_variable("nmbd_restart") || cgi_variable("all_restart")) { stop_nmbd(); start_nmbd(); waitup=True; } if (cgi_variable("nmbd_start") || cgi_variable("all_start")) { start_nmbd(); waitup=True; } if (cgi_variable("nmbd_stop")|| cgi_variable("all_stop")) { stop_nmbd(); waitup=True; } #ifdef WITH_WINBIND if (cgi_variable("winbindd_restart") || cgi_variable("all_restart")) { stop_winbindd(); start_winbindd(); waitup=True; } if (cgi_variable("winbindd_start") || cgi_variable("all_start")) { start_winbindd(); waitup=True; } if (cgi_variable("winbindd_stop") || cgi_variable("all_stop")) { stop_winbindd(); waitup=True; } #endif /* wait for daemons to start/stop */ if (waitup) sleep(SLEEP_TIME); if (cgi_variable("autorefresh")) { autorefresh = 1; } else if (cgi_variable("norefresh")) { autorefresh = 0; } else if (cgi_variable("refresh")) { autorefresh = 1; } if ((v=cgi_variable("refresh_interval"))) { refresh_interval = atoi(v); } if (cgi_variable("show_client_in_col_1")) { PID_or_Machine = 1; } if (cgi_variable("show_pid_in_col_1")) { PID_or_Machine = 0; } connections_forall_read(traverse_fn1, NULL); initPid2Machine (); output_page: printf("<H2>%s</H2>\n", _("Server Status")); printf("<FORM method=post>\n"); print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name); if (!autorefresh) { printf("<input type=submit value=\"%s\" name=\"autorefresh\">\n", _("Auto Refresh")); printf("<br>%s", _("Refresh Interval: ")); printf("<input type=text size=2 name=\"refresh_interval\" value=\"%d\">\n", refresh_interval); } else { printf("<input type=submit value=\"%s\" name=\"norefresh\">\n", _("Stop Refreshing")); printf("<br>%s%d\n", _("Refresh Interval: "), refresh_interval); printf("<input type=hidden name=\"refresh\" value=\"1\">\n"); } printf("<p>\n"); printf("<table>\n"); printf("<tr><td>%s</td><td>%s</td></tr>", _("version:"), samba_version_string()); fflush(stdout); printf("<tr><td>%s</td><td>%s</td>\n", _("smbd:"), smbd_running()?_("running"):_("not running")); if (geteuid() == 0) { if (smbd_running()) { nr_running++; printf("<td><input type=submit name=\"smbd_stop\" value=\"%s\"></td>\n", _("Stop smbd")); } else { printf("<td><input type=submit name=\"smbd_start\" value=\"%s\"></td>\n", _("Start smbd")); } printf("<td><input type=submit name=\"smbd_restart\" value=\"%s\"></td>\n", _("Restart smbd")); } printf("</tr>\n"); fflush(stdout); printf("<tr><td>%s</td><td>%s</td>\n", _("nmbd:"), nmbd_running()?_("running"):_("not running")); if (geteuid() == 0) { if (nmbd_running()) { nr_running++; printf("<td><input type=submit name=\"nmbd_stop\" value=\"%s\"></td>\n", _("Stop nmbd")); } else { printf("<td><input type=submit name=\"nmbd_start\" value=\"%s\"></td>\n", _("Start nmbd")); } printf("<td><input type=submit name=\"nmbd_restart\" value=\"%s\"></td>\n", _("Restart nmbd")); } printf("</tr>\n"); #ifdef WITH_WINBIND fflush(stdout); printf("<tr><td>%s</td><td>%s</td>\n", _("winbindd:"), winbindd_running()?_("running"):_("not running")); if (geteuid() == 0) { if (winbindd_running()) { nr_running++; printf("<td><input type=submit name=\"winbindd_stop\" value=\"%s\"></td>\n", _("Stop winbindd")); } else { printf("<td><input type=submit name=\"winbindd_start\" value=\"%s\"></td>\n", _("Start winbindd")); } printf("<td><input type=submit name=\"winbindd_restart\" value=\"%s\"></td>\n", _("Restart winbindd")); } printf("</tr>\n"); #endif if (geteuid() == 0) { printf("<tr><td></td><td></td>\n"); if (nr_running >= 1) { /* stop, restart all */ printf("<td><input type=submit name=\"all_stop\" value=\"%s\"></td>\n", _("Stop All")); printf("<td><input type=submit name=\"all_restart\" value=\"%s\"></td>\n", _("Restart All")); } else if (nr_running == 0) { /* start all */ printf("<td><input type=submit name=\"all_start\" value=\"%s\"></td>\n", _("Start All")); } printf("</tr>\n"); } printf("</table>\n"); fflush(stdout); printf("<p><h3>%s</h3>\n", _("Active Connections")); printf("<table border=1>\n"); printf("<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th>\n", _("PID"), _("Client"), _("IP address"), _("Date")); if (geteuid() == 0) { printf("<th>%s</th>\n", _("Kill")); } printf("</tr>\n"); connections_forall_read(traverse_fn2, NULL); printf("</table><p>\n"); printf("<p><h3>%s</h3>\n", _("Active Shares")); printf("<table border=1>\n"); printf("<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr>\n\n", _("Share"), _("User"), _("Group"), _("PID"), _("Client"), _("Date")); connections_forall_read(traverse_fn3, NULL); printf("</table><p>\n"); printf("<h3>%s</h3>\n", _("Open Files")); printf("<table border=1>\n"); printf("<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr>\n", _("PID"), _("UID"), _("Sharing"), _("R/W"), _("Oplock"), _("Share"), _("File"), _("Date")); locking_init_readonly(); share_mode_forall(print_share_mode, NULL); locking_end(); printf("</table>\n"); printf("<br><input type=submit name=\"show_client_in_col_1\" value=\"%s\">\n", _("Show Client in col 1")); printf("<input type=submit name=\"show_pid_in_col_1\" value=\"%s\">\n", _("Show PID in col 1")); printf("</FORM>\n"); if (autorefresh) { /* this little JavaScript allows for automatic refresh of the page. There are other methods but this seems to be the best alternative */ printf("<script language=\"JavaScript\">\n"); printf("<!--\nsetTimeout('window.location.replace(\"%s/status?refresh_interval=%d&refresh=1\")', %d)\n", cgi_baseurl(), refresh_interval, refresh_interval*1000); printf("//-->\n</script>\n"); } TALLOC_FREE(ctx); }
static bool fdpass2_parent(pid_t child_pid, int ready_fd) { struct tevent_context *ev = NULL; struct messaging_context *msg_ctx = NULL; bool retval = false; int up_pipe[2]; int down_pipe[2]; int pass_fds[2] = { 0 }; int ret; NTSTATUS status; struct server_id dst; TALLOC_CTX *frame = talloc_stackframe(); uint8_t c1 = 1, c2, c; ssize_t bytes; struct iovec iov; DATA_BLOB blob; struct tevent_fd *child_done_fde; struct child_done_state child_state; ev = samba_tevent_context_init(frame); if (ev == NULL) { fprintf(stderr, "parent: tevent_context_init failed\n"); goto done; } msg_ctx = messaging_init(ev, ev); if (msg_ctx == NULL) { fprintf(stderr, "parent: messaging_init failed\n"); goto done; } /* wait util the child is ready to receive messages */ bytes = read(ready_fd, &c, 1); if (bytes != 1) { perror("parent: read from ready_fd failed"); goto done; } ret = pipe(up_pipe); if (ret != 0) { perror("parent: pipe failed for up_pipe"); goto done; } ret = pipe(down_pipe); if (ret != 0) { perror("parent: pipe failed for down_pipe"); goto done; } child_state.fd = ready_fd; child_state.done = false; child_done_fde = tevent_add_fd(ev, ev, ready_fd, TEVENT_FD_READ, child_done_cb, &child_state); if (child_done_fde == NULL) { fprintf(stderr, "parent: failed tevent_add_fd for child done\n"); goto done; } pass_fds[0] = up_pipe[0]; pass_fds[1] = down_pipe[1]; dst = messaging_server_id(msg_ctx); dst.pid = child_pid; /* * Send a certain payload with the fds, to test to test * that fd-passing works when we have fragmentation and * re-assembly of the datagrams. */ blob = data_blob_talloc_zero(frame, 1000*1000); iov.iov_base = blob.data; iov.iov_len = blob.length; status = messaging_send_iov(msg_ctx, dst, MSG_TORTURE_FDPASS2, &iov, 1, pass_fds, 2); if (!NT_STATUS_IS_OK(status)) { fprintf(stderr, "parent: messaging_send_iov failed: %s\n", nt_errstr(status)); goto done; } printf("parent: waiting for child to confirm\n"); while (!child_state.done) { ret = tevent_loop_once(ev); if (ret != 0) { fprintf(stderr, "parent: tevent_loop_once failed\n"); goto done; } } printf("parent: child confirmed\n"); close(up_pipe[0]); close(down_pipe[1]); bytes = write(up_pipe[1], &c1, 1); if (bytes != 1) { perror("parent: write to up pipe failed"); goto done; } bytes = read(down_pipe[0], &c2, 1); if (bytes != 1) { perror("parent: read from down pipe failed"); goto done; } if (c1 != c2) { fprintf(stderr, "parent: c1[%d] != c2[%d]\n", c1, c2); goto done; } ret = waitpid(child_pid, NULL, 0); if (ret == -1) { perror("parent: waitpid failed"); goto done; } retval = true; done: TALLOC_FREE(frame); return retval; }
static bool srv_pipe_check_verification_trailer(struct pipes_struct *p, struct ncacn_packet *pkt, struct pipe_rpc_fns *pipe_fns) { TALLOC_CTX *frame = talloc_stackframe(); struct dcerpc_sec_verification_trailer *vt = NULL; const uint32_t bitmask1 = p->auth.client_hdr_signing ? DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0; const struct dcerpc_sec_vt_pcontext pcontext = { .abstract_syntax = pipe_fns->syntax, .transfer_syntax = ndr_transfer_syntax_ndr, }; const struct dcerpc_sec_vt_header2 header2 = dcerpc_sec_vt_header2_from_ncacn_packet(pkt); struct ndr_pull *ndr; enum ndr_err_code ndr_err; bool ret = false; ndr = ndr_pull_init_blob(&p->in_data.data, frame); if (ndr == NULL) { goto done; } ndr_err = ndr_pop_dcerpc_sec_verification_trailer(ndr, frame, &vt); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { goto done; } ret = dcerpc_sec_verification_trailer_check(vt, &bitmask1, &pcontext, &header2); done: TALLOC_FREE(frame); return ret; } /**************************************************************************** Find the correct RPC function to call for this request. If the pipe is authenticated then become the correct UNIX user before doing the call. ****************************************************************************/ static bool api_pipe_request(struct pipes_struct *p, struct ncacn_packet *pkt) { TALLOC_CTX *frame = talloc_stackframe(); bool ret = False; struct pipe_rpc_fns *pipe_fns; if (!p->pipe_bound) { DEBUG(1, ("Pipe not bound!\n")); data_blob_free(&p->out_data.rdata); TALLOC_FREE(frame); return false; } /* get the set of RPC functions for this context */ pipe_fns = find_pipe_fns_by_context(p->contexts, pkt->u.request.context_id); if (pipe_fns == NULL) { DEBUG(0, ("No rpc function table associated with context " "[%d]\n", pkt->u.request.context_id)); data_blob_free(&p->out_data.rdata); TALLOC_FREE(frame); return false; } if (!srv_pipe_check_verification_trailer(p, pkt, pipe_fns)) { DEBUG(1, ("srv_pipe_check_verification_trailer: failed\n")); setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_ACCESS_DENIED)); data_blob_free(&p->out_data.rdata); TALLOC_FREE(frame); return true; } if (!become_authenticated_pipe_user(p->session_info)) { DEBUG(1, ("Failed to become pipe user!\n")); data_blob_free(&p->out_data.rdata); TALLOC_FREE(frame); return false; } DEBUG(5, ("Requested %s rpc service\n", ndr_interface_name(&pipe_fns->syntax.uuid, pipe_fns->syntax.if_version))); ret = api_rpcTNP(p, pkt, pipe_fns->cmds, pipe_fns->n_cmds, &pipe_fns->syntax); unbecome_authenticated_pipe_user(); TALLOC_FREE(frame); return ret; }
/* this performs a SASL/SPNEGO bind */ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads) { TALLOC_CTX *frame = talloc_stackframe(); struct ads_service_principal p = {0}; struct berval *scred=NULL; int rc, i; ADS_STATUS status; DATA_BLOB blob; char *given_principal = NULL; char *OIDs[ASN1_MAX_OIDS]; #ifdef HAVE_KRB5 bool got_kerberos_mechanism = False; #endif rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", NULL, NULL, NULL, &scred); if (rc != LDAP_SASL_BIND_IN_PROGRESS) { status = ADS_ERROR(rc); goto done; } blob = data_blob(scred->bv_val, scred->bv_len); ber_bvfree(scred); #if 0 file_save("sasl_spnego.dat", blob.data, blob.length); #endif /* the server sent us the first part of the SPNEGO exchange in the negprot reply */ if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &given_principal, NULL) || OIDs[0] == NULL) { status = ADS_ERROR(LDAP_OPERATIONS_ERROR); goto done; } TALLOC_FREE(given_principal); /* make sure the server understands kerberos */ for (i=0;OIDs[i];i++) { DEBUG(3,("ads_sasl_spnego_bind: got OID=%s\n", OIDs[i])); #ifdef HAVE_KRB5 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 || strcmp(OIDs[i], OID_KERBEROS5) == 0) { got_kerberos_mechanism = True; } #endif talloc_free(OIDs[i]); } status = ads_generate_service_principal(ads, &p); if (!ADS_ERR_OK(status)) { goto done; } #ifdef HAVE_KRB5 if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) && got_kerberos_mechanism) { status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO", CRED_MUST_USE_KERBEROS, p.service, p.hostname, blob); if (ADS_ERR_OK(status)) { ads_free_service_principal(&p); goto done; } DEBUG(10,("ads_sasl_spnego_gensec_bind(KRB5) failed with: %s, " "calling kinit\n", ads_errstr(status))); status = ADS_ERROR_KRB5(ads_kinit_password(ads)); if (ADS_ERR_OK(status)) { status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO", CRED_MUST_USE_KERBEROS, p.service, p.hostname, blob); if (!ADS_ERR_OK(status)) { DEBUG(0,("kinit succeeded but " "ads_sasl_spnego_gensec_bind(KRB5) failed: %s\n", ads_errstr(status))); } } /* only fallback to NTLMSSP if allowed */ if (ADS_ERR_OK(status) || !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) { goto done; } } #endif /* lets do NTLMSSP ... this has the big advantage that we don't need to sync clocks, and we don't rely on special versions of the krb5 library for HMAC_MD4 encryption */ status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO", CRED_DONT_USE_KERBEROS, p.service, p.hostname, data_blob_null); done: ads_free_service_principal(&p); TALLOC_FREE(frame); return status; }