static char* passwd2string( const WINBINDD_PW *pw ) { static pstring string; int ret; if ( !pw || !pw->pw_name ) return NULL; DEBUG(10,("passwd2string: converting passwd struct for %s\n", pw->pw_name)); ret = pstr_sprintf( string, "%s:%s:%lu:%lu:%s:%s:%s", pw->pw_name, pw->pw_passwd ? pw->pw_passwd : "x", (unsigned long)pw->pw_uid, (unsigned long)pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell ); if ( ret < 0 ) { DEBUG(0,("passwd2string: pstr_sprintf() failed!\n")); return NULL; } return string; }
static BOOL make_full_path( pstring path, const char *server, const char *share, const char *dir ) { pstring servicename; char *sharename; const char *directory; /* make a copy so we don't modify the global string 'service' */ pstrcpy(servicename, share); sharename = servicename; if (*sharename == '\\') { server = sharename+2; sharename = strchr_m(server,'\\'); if (!sharename) return False; *sharename = 0; sharename++; } directory = dir; if ( *directory == '\\' ) directory++; pstr_sprintf( path, "\\%s\\%s\\%s", server, sharename, directory ); return True; }
BOOL regdb_store_values( const char *key, REGVAL_CTR *values ) { TDB_DATA data; pstring keystr; int len, ret; DEBUG(10,("regdb_store_values: Looking for value of key [%s] \n", key)); ZERO_STRUCT( data ); len = regdb_pack_values( values, data.dptr, data.dsize ); if ( len <= 0 ) { DEBUG(0,("regdb_store_values: unable to pack values. len <= 0\n")); return False; } data.dptr = SMB_MALLOC_ARRAY( char, len ); data.dsize = len; len = regdb_pack_values( values, data.dptr, data.dsize ); SMB_ASSERT( len == data.dsize ); pstr_sprintf( keystr, "%s/%s", VALUE_PREFIX, key ); normalize_reg_path( keystr ); ret = tdb_store_bystring(tdb_reg, keystr, data, TDB_REPLACE); SAFE_FREE( data.dptr ); return ret != -1 ; }
BOOL cli_check_msdfs_proxy( struct cli_state *cli, const char *sharename, fstring newserver, fstring newshare ) { CLIENT_DFS_REFERRAL *refs = NULL; size_t num_refs; uint16 consumed; pstring fullpath; BOOL res; uint16 cnum; pstring newextrapath; if ( !cli || !sharename ) return False; cnum = cli->cnum; /* special case. never check for a referral on the IPC$ share */ if ( strequal( sharename, "IPC$" ) ) { return False; } /* send a trans2_query_path_info to check for a referral */ pstr_sprintf( fullpath, "\\%s\\%s", cli->desthost, sharename ); /* check for the referral */ if (!cli_send_tconX(cli, "IPC$", "IPC", NULL, 0)) { return False; } res = cli_dfs_get_referral(cli, fullpath, &refs, &num_refs, &consumed); if (!cli_tdis(cli)) { SAFE_FREE( refs ); return False; } cli->cnum = cnum; if (!res || !num_refs ) { SAFE_FREE( refs ); return False; } split_dfs_path( refs[0].dfspath, newserver, newshare, newextrapath ); /* check that this is not a self-referral */ if ( strequal( cli->desthost, newserver ) && strequal( sharename, newshare ) ) { SAFE_FREE( refs ); return False; } SAFE_FREE( refs ); return True; }
/** * Form a key for fetching a trusted domain password * * @param domain trusted domain name * * @return stored password's key **/ static char *trustdom_keystr(const char *domain) { static pstring keystr; pstr_sprintf(keystr, "%s/%s", SECRETS_DOMTRUST_ACCT_PASS, domain); strupper_m(keystr); return keystr; }
static void cli_dfs_make_full_path( struct cli_state *cli, const char *dir, pstring path_out) { /* Ensure the extrapath doesn't start with a separator. */ while (IS_DIRECTORY_SEP(*dir)) { dir++; } pstr_sprintf( path_out, "\\%s\\%s\\%s", cli->desthost, cli->share, dir); }
static void terminate(void) { pstring path; idmap_close(); /* Remove socket file */ pstr_sprintf(path, "%s/%s", WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME); unlink(path); exit(0); }
static void set_logfile(poptContext con, const char * arg) { pstring logfile; const char *pname; /* Find out basename of current program */ pname = strrchr_m(poptGetInvocationName(con),'/'); if (!pname) pname = poptGetInvocationName(con); else pname++; #ifdef EMBED pstr_sprintf(logfile, "%s/smb_log.%s", arg, pname); #else pstr_sprintf(logfile, "%s/log.%s", arg, pname); #endif lp_set_logfile(logfile); }
static void offer_gss_spnego_mechs(void) { DATA_BLOB token; SPNEGO_DATA spnego; ssize_t len; char *reply_base64; pstring principal; pstring myname_lower; ZERO_STRUCT(spnego); pstrcpy(myname_lower, global_myname()); strlower_m(myname_lower); pstr_sprintf(principal, "%s$@%s", myname_lower, lp_realm()); /* Server negTokenInit (mech offerings) */ spnego.type = SPNEGO_NEG_TOKEN_INIT; spnego.negTokenInit.mechTypes = SMB_XMALLOC_ARRAY(const char *, 2); #ifdef HAVE_KRB5 spnego.negTokenInit.mechTypes[0] = smb_xstrdup(OID_KERBEROS5_OLD); spnego.negTokenInit.mechTypes[1] = smb_xstrdup(OID_NTLMSSP); spnego.negTokenInit.mechTypes[2] = NULL; #else spnego.negTokenInit.mechTypes[0] = smb_xstrdup(OID_NTLMSSP); spnego.negTokenInit.mechTypes[1] = NULL; #endif spnego.negTokenInit.mechListMIC = data_blob(principal, strlen(principal)); len = write_spnego_data(&token, &spnego); free_spnego_data(&spnego); if (len == -1) { DEBUG(1, ("Could not write SPNEGO data blob\n")); x_fprintf(x_stdout, "BH\n"); return; } reply_base64 = base64_encode_data_blob(token); x_fprintf(x_stdout, "TT %s *\n", reply_base64); SAFE_FREE(reply_base64); data_blob_free(&token); DEBUG(10, ("sent SPNEGO negTokenInit\n")); return; }
int regdb_fetch_values( const char* key, REGVAL_CTR *values ) { TDB_DATA data; pstring keystr; DEBUG(10,("regdb_fetch_values: Looking for value of key [%s] \n", key)); pstr_sprintf( keystr, "%s/%s", VALUE_PREFIX, key ); normalize_reg_path( keystr ); data = tdb_fetch_bystring( tdb_reg, keystr ); if ( !data.dptr ) { /* all keys have zero values by default */ return 0; } regdb_unpack_values( values, data.dptr, data.dsize ); SAFE_FREE( data.dptr ); return regval_ctr_numvals(values); }
static void *find_fn(const char *name) { pstring s; static void *h; void *res; pstr_sprintf(s, "_nss_%s_%s", nss_name, name); if (!h) { h = sys_dlopen(so_path, RTLD_LAZY); } if (!h) { printf("Can't open shared library %s\n", so_path); exit(1); } res = sys_dlsym(h, s); if (!res) { printf("Can't find function %s\n", s); total_errors++; return NULL; } return res; }
static int cups_job_submit(int snum, struct printjob *pjob) { int ret; /* Return value */ http_t *http; /* HTTP connection to server */ ipp_t *request, /* IPP Request */ *response; /* IPP Response */ cups_lang_t *language; /* Default language */ char uri[HTTP_MAX_URI]; /* printer-uri attribute */ char *clientname; /* hostname of client for job-originating-host attribute */ pstring new_jobname; int num_options = 0; cups_option_t *options; DEBUG(5,("cups_job_submit(%d, %p (%d))\n", snum, pjob, pjob->sysjob)); /* * Make sure we don't ask for passwords... */ cupsSetPasswordCB(cups_passwd_cb); /* * Try to connect to the server... */ if ((http = httpConnect(cupsServer(), ippPort())) == NULL) { DEBUG(0,("Unable to connect to CUPS server %s - %s\n", cupsServer(), strerror(errno))); return (1); } /* * Build an IPP_PRINT_JOB request, which requires the following * attributes: * * attributes-charset * attributes-natural-language * printer-uri * requesting-user-name * [document-data] */ request = ippNew(); request->request.op.operation_id = IPP_PRINT_JOB; request->request.op.request_id = 1; language = cupsLangDefault(); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, "attributes-charset", NULL, cupsLangEncoding(language)); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, language->language); slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", PRINTERNAME(snum)); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, pjob->user); clientname = client_name(); if (strcmp(clientname, "UNKNOWN") == 0) { clientname = client_addr(); } ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-originating-host-name", NULL, clientname); pstr_sprintf(new_jobname,"%s%.8u %s", PRINT_SPOOL_PREFIX, (unsigned int)pjob->smbjob, pjob->jobname); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, new_jobname); /* * add any options defined in smb.conf */ num_options = 0; options = NULL; num_options = cupsParseOptions(lp_cups_options(snum), num_options, &options); if ( num_options ) cupsEncodeOptions(request, num_options, options); /* * Do the request and get back a response... */ slprintf(uri, sizeof(uri) - 1, "/printers/%s", PRINTERNAME(snum)); ret = 1; if ((response = cupsDoFileRequest(http, request, uri, pjob->filename)) != NULL) { if (response->request.status.status_code >= IPP_OK_CONFLICT) DEBUG(0,("Unable to print file to %s - %s\n", PRINTERNAME(snum), ippErrorString(cupsLastError()))); else ret = 0; ippDelete(response); } else DEBUG(0,("Unable to print file to `%s' - %s\n", PRINTERNAME(snum), ippErrorString(cupsLastError()))); httpClose(http); if ( ret == 0 ) unlink(pjob->filename); /* else print_job_end will do it for us */ return (ret); }
BOOL cli_resolve_path( const char *mountpt, struct cli_state *rootcli, const char *path, struct cli_state **targetcli, pstring targetpath) { CLIENT_DFS_REFERRAL *refs = NULL; size_t num_refs; uint16 consumed; struct cli_state *cli_ipc; pstring dfs_path, cleanpath, extrapath; int pathlen; fstring server, share; struct cli_state *newcli; pstring newpath; pstring newmount; char *ppath, *temppath = NULL; SMB_STRUCT_STAT sbuf; uint32 attributes; if ( !rootcli || !path || !targetcli ) { return False; } /* Don't do anything if this is not a DFS root. */ if ( !rootcli->dfsroot) { *targetcli = rootcli; pstrcpy( targetpath, path ); return True; } *targetcli = NULL; /* Send a trans2_query_path_info to check for a referral. */ clean_path(path, cleanpath); cli_dfs_make_full_path(rootcli, cleanpath, dfs_path ); if (cli_qpathinfo_basic( rootcli, dfs_path, &sbuf, &attributes ) ) { /* This is an ordinary path, just return it. */ *targetcli = rootcli; pstrcpy( targetpath, path ); goto done; } /* Special case where client asked for a path that does not exist */ if ( cli_dfs_check_error(rootcli, NT_STATUS_OBJECT_NAME_NOT_FOUND) ) { *targetcli = rootcli; pstrcpy( targetpath, path ); goto done; } /* We got an error, check for DFS referral. */ if ( !cli_dfs_check_error(rootcli, NT_STATUS_PATH_NOT_COVERED)) { return False; } /* Check for the referral. */ if ( !(cli_ipc = cli_cm_open( rootcli->desthost, "IPC$", False )) ) { return False; } if ( !cli_dfs_get_referral(cli_ipc, dfs_path, &refs, &num_refs, &consumed) || !num_refs ) { return False; } /* Just store the first referral for now. */ split_dfs_path( refs[0].dfspath, server, share, extrapath ); SAFE_FREE(refs); /* Make sure to recreate the original string including any wildcards. */ cli_dfs_make_full_path( rootcli, path, dfs_path); pathlen = strlen( dfs_path )*2; consumed = MIN(pathlen, consumed ); pstrcpy( targetpath, &dfs_path[consumed/2] ); dfs_path[consumed/2] = '\0'; /* * targetpath is now the unconsumed part of the path. * dfs_path is now the consumed part of the path (in \server\share\path format). */ /* Open the connection to the target server & share */ if ( (*targetcli = cli_cm_open(server, share, False)) == NULL ) { d_printf("Unable to follow dfs referral [\\%s\\%s]\n", server, share ); return False; } if (strlen(extrapath) > 0) { string_append(&temppath, extrapath); string_append(&temppath, targetpath); pstrcpy( targetpath, temppath ); } /* parse out the consumed mount path */ /* trim off the \server\share\ */ ppath = dfs_path; if (*ppath != '\\') { d_printf("cli_resolve_path: dfs_path (%s) not in correct format.\n", dfs_path ); return False; } ppath++; /* Now pointing at start of server name. */ if ((ppath = strchr_m( dfs_path, '\\' )) == NULL) { return False; } ppath++; /* Now pointing at start of share name. */ if ((ppath = strchr_m( ppath+1, '\\' )) == NULL) { return False; } ppath++; /* Now pointing at path component. */ pstr_sprintf( newmount, "%s\\%s", mountpt, ppath ); cli_cm_set_mntpoint( *targetcli, newmount ); /* Check for another dfs referral, note that we are not checking for loops here. */ if ( !strequal( targetpath, "\\" ) && !strequal( targetpath, "/")) { if ( cli_resolve_path( newmount, *targetcli, targetpath, &newcli, newpath ) ) { /* * When cli_resolve_path returns true here it's always * returning the complete path in newpath, so we're done * here. */ *targetcli = newcli; pstrcpy( targetpath, newpath ); return True; } } done: /* If returning True ensure we return a dfs root full path. */ if ( (*targetcli)->dfsroot ) { pstrcpy(dfs_path, targetpath ); cli_dfs_make_full_path( *targetcli, dfs_path, targetpath); } return True; }
static void popt_common_credentials_callback(poptContext con, enum poptCallbackReason reason, const struct poptOption *opt, const char *arg, const void *data) { char *p; if (reason == POPT_CALLBACK_REASON_PRE) { cmdline_auth_info.use_kerberos = False; cmdline_auth_info.got_pass = False; cmdline_auth_info.signing_state = Undefined; pstrcpy(cmdline_auth_info.username, "GUEST"); if (getenv("LOGNAME"))pstrcpy(cmdline_auth_info.username,getenv("LOGNAME")); if (getenv("USER")) { pstrcpy(cmdline_auth_info.username,getenv("USER")); if ((p = strchr_m(cmdline_auth_info.username,'%'))) { *p = 0; pstrcpy(cmdline_auth_info.password,p+1); cmdline_auth_info.got_pass = True; memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(cmdline_auth_info.password)); } } if (getenv("PASSWD")) { pstrcpy(cmdline_auth_info.password,getenv("PASSWD")); cmdline_auth_info.got_pass = True; } if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) { get_password_file(&cmdline_auth_info); cmdline_auth_info.got_pass = True; } return; } switch(opt->val) { case 'U': { char *lp; pstrcpy(cmdline_auth_info.username,arg); if ((lp=strchr_m(cmdline_auth_info.username,'%'))) { *lp = 0; pstrcpy(cmdline_auth_info.password,lp+1); cmdline_auth_info.got_pass = True; memset(strchr_m(arg,'%')+1,'X',strlen(cmdline_auth_info.password)); } } break; case 'A': get_credentials_file(arg, &cmdline_auth_info); break; case 'k': #ifndef HAVE_KRB5 d_printf("No kerberos support compiled in\n"); exit(1); #else cmdline_auth_info.use_kerberos = True; cmdline_auth_info.got_pass = True; #endif break; case 'S': { cmdline_auth_info.signing_state = -1; if (strequal(arg, "off") || strequal(arg, "no") || strequal(arg, "false")) cmdline_auth_info.signing_state = False; else if (strequal(arg, "on") || strequal(arg, "yes") || strequal(arg, "true") || strequal(arg, "auto") ) cmdline_auth_info.signing_state = True; else if (strequal(arg, "force") || strequal(arg, "required") || strequal(arg, "forced")) cmdline_auth_info.signing_state = Required; else { fprintf(stderr, "Unknown signing option %s\n", arg ); exit(1); } } break; case 'P': { char *opt_password = NULL; /* it is very useful to be able to make ads queries as the machine account for testing purposes and for domain leave */ if (!secrets_init()) { d_printf("ERROR: Unable to open secrets database\n"); exit(1); } opt_password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); if (!opt_password) { d_printf("ERROR: Unable to fetch machine password\n"); exit(1); } pstr_sprintf(cmdline_auth_info.username, "%s$", global_myname()); pstrcpy(cmdline_auth_info.password,opt_password); SAFE_FREE(opt_password); /* machine accounts only work with kerberos */ cmdline_auth_info.use_kerberos = True; cmdline_auth_info.got_pass = True; } break; } }
int create_pipe_sock(const char *socket_dir, const char *socket_name, mode_t dir_perms) { #ifdef HAVE_UNIXSOCKET struct sockaddr_un sunaddr; struct stat st; int sock; mode_t old_umask; pstring path; old_umask = umask(0); /* Create the socket directory or reuse the existing one */ if (lstat(socket_dir, &st) == -1) { if (errno == ENOENT) { /* Create directory */ if (mkdir(socket_dir, dir_perms) == -1) { DEBUG(0, ("error creating socket directory " "%s: %s\n", socket_dir, strerror(errno))); goto out_umask; } } else { DEBUG(0, ("lstat failed on socket directory %s: %s\n", socket_dir, strerror(errno))); goto out_umask; } } else { /* Check ownership and permission on existing directory */ if (!S_ISDIR(st.st_mode)) { DEBUG(0, ("socket directory %s isn't a directory\n", socket_dir)); goto out_umask; } if ((st.st_uid != sec_initial_uid()) || ((st.st_mode & 0777) != dir_perms)) { DEBUG(0, ("invalid permissions on socket directory " "%s\n", socket_dir)); goto out_umask; } } /* Create the socket file */ sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock == -1) { perror("socket"); goto out_umask; } pstr_sprintf(path, "%s/%s", socket_dir, socket_name); unlink(path); memset(&sunaddr, 0, sizeof(sunaddr)); sunaddr.sun_family = AF_UNIX; safe_strcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)-1); if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) { DEBUG(0, ("bind failed on pipe socket %s: %s\n", path, strerror(errno))); goto out_close; } if (listen(sock, 5) == -1) { DEBUG(0, ("listen failed on pipe socket %s: %s\n", path, strerror(errno))); goto out_close; } umask(old_umask); return sock; out_close: close(sock); out_umask: umask(old_umask); return -1; #else DEBUG(0, ("create_pipe_sock: No Unix sockets on this system\n")); return -1; #endif /* HAVE_UNIXSOCKET */ }
static void popt_common_callback(poptContext con, enum poptCallbackReason reason, const struct poptOption *opt, const char *arg, const void *data) { if (reason == POPT_CALLBACK_REASON_PRE) { set_logfile(con, dyn_LOGFILEBASE); return; } switch(opt->val) { case 'd': if (arg) { debug_parse_levels(arg); AllowDebugChange = False; } break; case 'V': printf( "Version %s\n", SAMBA_VERSION_STRING); exit(0); break; case 'O': if (arg) { pstrcpy(user_socket_options,arg); } break; case 's': if (arg) { pstrcpy(dyn_CONFIGFILE, arg); } break; case 'n': if (arg) { set_global_myname(arg); } break; case 'l': if (arg) { set_logfile(con, arg); override_logfile = True; pstr_sprintf(dyn_LOGFILEBASE, "%s", arg); } break; case 'i': if (arg) { set_global_scope(arg); } break; case 'W': if (arg) { set_global_myworkgroup(arg); } break; } }
BOOL cli_resolve_path( const char *mountpt, struct cli_state *rootcli, const char *path, struct cli_state **targetcli, pstring targetpath ) { CLIENT_DFS_REFERRAL *refs = NULL; size_t num_refs; uint16 consumed; struct cli_state *cli_ipc; pstring fullpath, cleanpath; int pathlen; fstring server, share; struct cli_state *newcli; pstring newpath; pstring newmount; char *ppath; SMB_STRUCT_STAT sbuf; uint32 attributes; *targetcli = NULL; if ( !rootcli || !path || !targetcli ) return False; /* send a trans2_query_path_info to check for a referral */ clean_path( cleanpath, path ); make_full_path( fullpath, rootcli->desthost, rootcli->share, cleanpath ); /* don't bother continuing if this is not a dfs root */ if ( !rootcli->dfsroot || cli_qpathinfo_basic( rootcli, cleanpath, &sbuf, &attributes ) ) { *targetcli = rootcli; pstrcpy( targetpath, path ); return True; } /* we got an error, check for DFS referral */ if ( !cli_dfs_check_error(rootcli) ) return False; /* check for the referral */ if ( !(cli_ipc = cli_cm_open( rootcli->desthost, "IPC$", False )) ) return False; if ( !cli_dfs_get_referral(cli_ipc, fullpath, &refs, &num_refs, &consumed) || !num_refs ) { return False; } /* just store the first referral for now Make sure to recreate the original string including any wildcards */ make_full_path( fullpath, rootcli->desthost, rootcli->share, path ); pathlen = strlen( fullpath )*2; consumed = MIN(pathlen, consumed ); pstrcpy( targetpath, &fullpath[consumed/2] ); split_dfs_path( refs[0].dfspath, server, share ); SAFE_FREE( refs ); /* open the connection to the target path */ if ( (*targetcli = cli_cm_open(server, share, False)) == NULL ) { d_printf("Unable to follow dfs referral [//%s/%s]\n", server, share ); return False; } /* parse out the consumed mount path */ /* trim off the \server\share\ */ fullpath[consumed/2] = '\0'; dos_clean_name( fullpath ); ppath = strchr_m( fullpath, '\\' ); ppath = strchr_m( ppath+1, '\\' ); ppath = strchr_m( ppath+1, '\\' ); ppath++; pstr_sprintf( newmount, "%s\\%s", mountpt, ppath ); cli_cm_set_mntpoint( *targetcli, newmount ); /* check for another dfs referral, note that we are not checking for loops here */ if ( !strequal( targetpath, "\\" ) ) { if ( cli_resolve_path( newmount, *targetcli, targetpath, &newcli, newpath ) ) { *targetcli = newcli; pstrcpy( targetpath, newpath ); } } return True; }
static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode, char *buf, int length) { static NTLMSSP_STATE *ntlmssp_state = NULL; SPNEGO_DATA request, response; DATA_BLOB token; NTSTATUS status; ssize_t len; char *user = NULL; char *domain = NULL; const char *reply_code; char *reply_base64; pstring reply_argument; if (strlen(buf) < 2) { DEBUG(1, ("SPENGO query [%s] invalid", buf)); x_fprintf(x_stdout, "BH\n"); return; } if (strncmp(buf, "YR", 2) == 0) { if (ntlmssp_state) ntlmssp_end(&ntlmssp_state); } else if (strncmp(buf, "KK", 2) == 0) { } else { DEBUG(1, ("SPENGO query [%s] invalid", buf)); x_fprintf(x_stdout, "BH\n"); return; } if ( (strlen(buf) == 2)) { /* no client data, get the negTokenInit offering mechanisms */ offer_gss_spnego_mechs(); return; } /* All subsequent requests have a blob. This might be negTokenInit or negTokenTarg */ if (strlen(buf) <= 3) { DEBUG(1, ("GSS-SPNEGO query [%s] invalid\n", buf)); x_fprintf(x_stdout, "BH\n"); return; } token = base64_decode_data_blob(buf + 3); len = read_spnego_data(token, &request); data_blob_free(&token); if (len == -1) { DEBUG(1, ("GSS-SPNEGO query [%s] invalid", buf)); x_fprintf(x_stdout, "BH\n"); return; } if (request.type == SPNEGO_NEG_TOKEN_INIT) { /* Second request from Client. This is where the client offers its mechanism to use. */ if ( (request.negTokenInit.mechTypes == NULL) || (request.negTokenInit.mechTypes[0] == NULL) ) { DEBUG(1, ("Client did not offer any mechanism")); x_fprintf(x_stdout, "BH\n"); return; } status = NT_STATUS_UNSUCCESSFUL; if (strcmp(request.negTokenInit.mechTypes[0], OID_NTLMSSP) == 0) { if ( request.negTokenInit.mechToken.data == NULL ) { DEBUG(1, ("Client did not provide NTLMSSP data\n")); x_fprintf(x_stdout, "BH\n"); return; } if ( ntlmssp_state != NULL ) { DEBUG(1, ("Client wants a new NTLMSSP challenge, but " "already got one\n")); x_fprintf(x_stdout, "BH\n"); ntlmssp_end(&ntlmssp_state); return; } if (!NT_STATUS_IS_OK(status = ntlm_auth_start_ntlmssp_server(&ntlmssp_state))) { x_fprintf(x_stdout, "BH %s\n", nt_errstr(status)); return; } DEBUG(10, ("got NTLMSSP packet:\n")); dump_data(10, (const char *)request.negTokenInit.mechToken.data, request.negTokenInit.mechToken.length); response.type = SPNEGO_NEG_TOKEN_TARG; response.negTokenTarg.supportedMech = SMB_STRDUP(OID_NTLMSSP); response.negTokenTarg.mechListMIC = data_blob(NULL, 0); status = ntlmssp_update(ntlmssp_state, request.negTokenInit.mechToken, &response.negTokenTarg.responseToken); } #ifdef HAVE_KRB5 if (strcmp(request.negTokenInit.mechTypes[0], OID_KERBEROS5_OLD) == 0) { TALLOC_CTX *mem_ctx = talloc_init("manage_gss_spnego_request"); char *principal; DATA_BLOB ap_rep; DATA_BLOB session_key; if ( request.negTokenInit.mechToken.data == NULL ) { DEBUG(1, ("Client did not provide Kerberos data\n")); x_fprintf(x_stdout, "BH\n"); return; } response.type = SPNEGO_NEG_TOKEN_TARG; response.negTokenTarg.supportedMech = SMB_STRDUP(OID_KERBEROS5_OLD); response.negTokenTarg.mechListMIC = data_blob(NULL, 0); response.negTokenTarg.responseToken = data_blob(NULL, 0); status = ads_verify_ticket(mem_ctx, lp_realm(), 0, &request.negTokenInit.mechToken, &principal, NULL, &ap_rep, &session_key); talloc_destroy(mem_ctx); /* Now in "principal" we have the name we are authenticated as. */ if (NT_STATUS_IS_OK(status)) { domain = strchr_m(principal, '@'); if (domain == NULL) { DEBUG(1, ("Did not get a valid principal " "from ads_verify_ticket\n")); x_fprintf(x_stdout, "BH\n"); return; } *domain++ = '\0'; domain = SMB_STRDUP(domain); user = SMB_STRDUP(principal); data_blob_free(&ap_rep); SAFE_FREE(principal); } } #endif } else { if ( (request.negTokenTarg.supportedMech == NULL) || ( strcmp(request.negTokenTarg.supportedMech, OID_NTLMSSP) != 0 ) ) { /* Kerberos should never send a negTokenTarg, OID_NTLMSSP is the only one we support that sends this stuff */ DEBUG(1, ("Got a negTokenTarg for something non-NTLMSSP: %s\n", request.negTokenTarg.supportedMech)); x_fprintf(x_stdout, "BH\n"); return; } if (request.negTokenTarg.responseToken.data == NULL) { DEBUG(1, ("Got a negTokenTarg without a responseToken!\n")); x_fprintf(x_stdout, "BH\n"); return; } status = ntlmssp_update(ntlmssp_state, request.negTokenTarg.responseToken, &response.negTokenTarg.responseToken); response.type = SPNEGO_NEG_TOKEN_TARG; response.negTokenTarg.supportedMech = SMB_STRDUP(OID_NTLMSSP); response.negTokenTarg.mechListMIC = data_blob(NULL, 0); if (NT_STATUS_IS_OK(status)) { user = SMB_STRDUP(ntlmssp_state->user); domain = SMB_STRDUP(ntlmssp_state->domain); ntlmssp_end(&ntlmssp_state); } } free_spnego_data(&request); if (NT_STATUS_IS_OK(status)) { response.negTokenTarg.negResult = SPNEGO_ACCEPT_COMPLETED; reply_code = "AF"; pstr_sprintf(reply_argument, "%s\\%s", domain, user); } else if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { response.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE; reply_code = "TT"; pstr_sprintf(reply_argument, "*"); } else { response.negTokenTarg.negResult = SPNEGO_REJECT; reply_code = "NA"; pstrcpy(reply_argument, nt_errstr(status)); } SAFE_FREE(user); SAFE_FREE(domain); len = write_spnego_data(&token, &response); free_spnego_data(&response); if (len == -1) { DEBUG(1, ("Could not write SPNEGO data blob\n")); x_fprintf(x_stdout, "BH\n"); return; } reply_base64 = base64_encode_data_blob(token); x_fprintf(x_stdout, "%s %s %s\n", reply_code, reply_base64, reply_argument); SAFE_FREE(reply_base64); data_blob_free(&token); return; }
static BOOL manage_client_krb5_init(SPNEGO_DATA spnego) { char *principal; DATA_BLOB tkt, to_server; DATA_BLOB session_key_krb5 = data_blob(NULL, 0); SPNEGO_DATA reply; char *reply_base64; int retval; const char *my_mechs[] = {OID_KERBEROS5_OLD, NULL}; ssize_t len; if ( (spnego.negTokenInit.mechListMIC.data == NULL) || (spnego.negTokenInit.mechListMIC.length == 0) ) { DEBUG(1, ("Did not get a principal for krb5\n")); return False; } principal = SMB_MALLOC(spnego.negTokenInit.mechListMIC.length+1); if (principal == NULL) { DEBUG(1, ("Could not malloc principal\n")); return False; } memcpy(principal, spnego.negTokenInit.mechListMIC.data, spnego.negTokenInit.mechListMIC.length); principal[spnego.negTokenInit.mechListMIC.length] = '\0'; retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0, NULL); if (retval) { pstring user; /* Let's try to first get the TGT, for that we need a password. */ if (opt_password == NULL) { DEBUG(10, ("Requesting password\n")); x_fprintf(x_stdout, "PW\n"); return True; } pstr_sprintf(user, "%s@%s", opt_username, opt_domain); if ((retval = kerberos_kinit_password(user, opt_password, 0, NULL))) { DEBUG(10, ("Requesting TGT failed: %s\n", error_message(retval))); return False; } retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0, NULL); if (retval) { DEBUG(10, ("Kinit suceeded, but getting a ticket failed: %s\n", error_message(retval))); return False; } } data_blob_free(&session_key_krb5); ZERO_STRUCT(reply); reply.type = SPNEGO_NEG_TOKEN_INIT; reply.negTokenInit.mechTypes = my_mechs; reply.negTokenInit.reqFlags = 0; reply.negTokenInit.mechToken = tkt; reply.negTokenInit.mechListMIC = data_blob(NULL, 0); len = write_spnego_data(&to_server, &reply); data_blob_free(&tkt); if (len == -1) { DEBUG(1, ("Could not write SPNEGO data blob\n")); return False; } reply_base64 = base64_encode_data_blob(to_server); x_fprintf(x_stdout, "KK %s *\n", reply_base64); SAFE_FREE(reply_base64); data_blob_free(&to_server); DEBUG(10, ("sent GSS-SPNEGO KERBEROS5 negTokenInit\n")); return True; }
/**************************************************************************** send a qpathinfo BASIC_INFO call ****************************************************************************/ BOOL cli_qpathinfo_basic( struct cli_state *cli, const char *name, SMB_STRUCT_STAT *sbuf, uint32 *attributes ) { unsigned int param_len = 0; unsigned int data_len = 0; uint16 setup = TRANSACT2_QPATHINFO; char param[sizeof(pstring)+6]; char *rparam=NULL, *rdata=NULL; char *p; pstring path; int len; /* send full paths to dfs root shares */ if ( cli->dfsroot ) pstr_sprintf(path, "\\%s\\%s\\%s", cli->desthost, cli->share, name ); else pstrcpy( path, name ); /* cleanup */ len = strlen( path ); if ( path[len] == '\\' ) path[len] = '\0'; p = param; memset(p, 0, 6); SSVAL(p, 0, SMB_QUERY_FILE_BASIC_INFO); p += 6; p += clistr_push(cli, p, path, sizeof(pstring)-6, STR_TERMINATE); param_len = PTR_DIFF(p, param); if (!cli_send_trans(cli, SMBtrans2, NULL, /* name */ -1, 0, /* fid, flags */ &setup, 1, 0, /* setup, length, max */ param, param_len, 2, /* param, length, max */ NULL, 0, cli->max_xmit /* data, length, max */ )) { return False; } if (!cli_receive_trans(cli, SMBtrans2, &rparam, ¶m_len, &rdata, &data_len)) { return False; } if (data_len < 36) { SAFE_FREE(rdata); SAFE_FREE(rparam); return False; } sbuf->st_atime = interpret_long_date( rdata+8 ); /* Access time. */ sbuf->st_mtime = interpret_long_date( rdata+16 ); /* Write time. */ sbuf->st_ctime = interpret_long_date( rdata+24 ); /* Change time. */ *attributes = IVAL( rdata, 32 ); SAFE_FREE(rparam); SAFE_FREE(rdata); return True; }
int main(int argc, char **argv) { pstring logfile; static BOOL interactive = False; static BOOL Fork = True; static BOOL log_stdout = False; struct poptOption long_options[] = { POPT_AUTOHELP { "stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, { "foreground", 'F', POPT_ARG_VAL, &Fork, False, "Daemon in foreground mode" }, { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" }, { "single-daemon", 'Y', POPT_ARG_VAL, &opt_dual_daemon, False, "Single daemon mode" }, { "no-caching", 'n', POPT_ARG_VAL, &opt_nocache, True, "Disable caching" }, POPT_COMMON_SAMBA POPT_TABLEEND }; poptContext pc; int opt; /* glibc (?) likes to print "User defined signal 1" and exit if a SIGUSR[12] is received before a handler is installed */ CatchSignal(SIGUSR1, SIG_IGN); CatchSignal(SIGUSR2, SIG_IGN); fault_setup((void (*)(void *))fault_quit ); /* Initialise for running in non-root mode */ sec_init(); set_remote_machine_name("winbindd", False); /* Set environment variable so we don't recursively call ourselves. This may also be useful interactively. */ setenv(WINBINDD_DONT_ENV, "1", 1); /* Initialise samba/rpc client stuff */ pc = poptGetContext("winbindd", argc, (const char **)argv, long_options, POPT_CONTEXT_KEEP_FIRST); while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { /* Don't become a daemon */ case 'i': interactive = True; log_stdout = True; Fork = False; break; } } if (log_stdout && Fork) { printf("Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n"); poptPrintUsage(pc, stderr, 0); exit(1); } pstr_sprintf(logfile, "%s/log.winbindd", dyn_LOGFILEBASE); lp_set_logfile(logfile); setup_logging("winbindd", log_stdout); reopen_logs(); DEBUG(1, ("winbindd version %s started.\n", SAMBA_VERSION_STRING) ); DEBUGADD( 1, ( "Copyright The Samba Team 2000-2004\n" ) ); if (!reload_services_file()) { DEBUG(0, ("error opening config file\n")); exit(1); } /* Setup names. */ if (!init_names()) exit(1); load_interfaces(); if (!secrets_init()) { DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n")); return False; } /* Enable netbios namecache */ namecache_enable(); /* Check winbindd parameters are valid */ ZERO_STRUCT(server_state); /* Winbind daemon initialisation */ if ( (!winbindd_param_init()) || (!winbindd_upgrade_idmap()) || (!idmap_init(lp_idmap_backend())) ) { DEBUG(1, ("Could not init idmap -- netlogon proxy only\n")); idmap_proxyonly(); } generate_wellknown_sids(); /* Unblock all signals we are interested in as they may have been blocked by the parent process. */ BlockSignals(False, SIGINT); BlockSignals(False, SIGQUIT); BlockSignals(False, SIGTERM); BlockSignals(False, SIGUSR1); BlockSignals(False, SIGUSR2); BlockSignals(False, SIGHUP); BlockSignals(False, SIGCHLD); /* Setup signal handlers */ CatchSignal(SIGINT, termination_handler); /* Exit on these sigs */ CatchSignal(SIGQUIT, termination_handler); CatchSignal(SIGTERM, termination_handler); CatchSignal(SIGCHLD, sigchld_handler); CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */ CatchSignal(SIGUSR2, sigusr2_handler); /* Debugging sigs */ CatchSignal(SIGHUP, sighup_handler); if (!interactive) become_daemon(Fork); pidfile_create("winbindd"); #if HAVE_SETPGID /* * If we're interactive we want to set our own process group for * signal management. */ if (interactive) setpgid( (pid_t)0, (pid_t)0); #endif if (opt_dual_daemon) { do_dual_daemon(); } /* Initialise messaging system */ if (!message_init()) { DEBUG(0, ("unable to initialise messaging system\n")); exit(1); } /* React on 'smbcontrol winbindd reload-config' in the same way as to SIGHUP signal */ message_register(MSG_SMB_CONF_UPDATED, msg_reload_services); message_register(MSG_SHUTDOWN, msg_shutdown); poptFreeContext(pc); netsamlogon_cache_init(); /* Non-critical */ init_domain_list(); /* Loop waiting for requests */ process_loop(); trustdom_cache_shutdown(); return 0; }
static void popt_common_callback(poptContext con, enum poptCallbackReason reason, const struct poptOption *opt, const char *arg, const void *data) { pstring logfile; const char *pname; /* Find out basename of current program */ pname = strrchr_m(poptGetInvocationName(con),'/'); if (!pname) pname = poptGetInvocationName(con); else pname++; if (reason == POPT_CALLBACK_REASON_PRE) { pstr_sprintf(logfile, "%s/log.%s", dyn_LOGFILEBASE, pname); lp_set_logfile(logfile); return; } switch(opt->val) { case 'd': if (arg) { debug_parse_levels(arg); AllowDebugChange = False; } break; case 'V': printf( "Version %s\n", SAMBA_VERSION_STRING); exit(0); break; case 'O': if (arg) { pstrcpy(user_socket_options,arg); } break; case 's': if (arg) { pstrcpy(dyn_CONFIGFILE, arg); } break; case 'n': if (arg) { set_global_myname(arg); } break; case 'l': if (arg) { pstr_sprintf(logfile, "%s/log.%s", arg, pname); lp_set_logfile(logfile); } break; case 'i': if (arg) { set_global_scope(arg); } break; case 'W': if (arg) { set_global_myworkgroup(arg); } break; } }
BOOL regdb_store_keys( const char *key, REGSUBKEY_CTR *ctr ) { int num_subkeys, i; pstring path; REGSUBKEY_CTR *subkeys, *old_subkeys; char *oldkeyname; /* fetch a list of the old subkeys so we can determine if any were deleted */ if ( !(old_subkeys = TALLOC_ZERO_P( ctr, REGSUBKEY_CTR )) ) { DEBUG(0,("regdb_store_keys: talloc() failure!\n")); return False; } regdb_fetch_keys( key, old_subkeys ); /* store the subkey list for the parent */ if ( !regdb_store_keys_internal( key, ctr ) ) { DEBUG(0,("regdb_store_keys: Failed to store new subkey list for parent [%s}\n", key )); return False; } /* now delete removed keys */ num_subkeys = regsubkey_ctr_numkeys( old_subkeys ); for ( i=0; i<num_subkeys; i++ ) { oldkeyname = regsubkey_ctr_specific_key( old_subkeys, i ); if ( !regsubkey_ctr_key_exists( ctr, oldkeyname ) ) { pstr_sprintf( path, "%s%c%s", key, '/', oldkeyname ); normalize_reg_path( path ); tdb_delete_bystring( tdb_reg, path ); } } TALLOC_FREE( old_subkeys ); /* now create records for any subkeys that don't already exist */ num_subkeys = regsubkey_ctr_numkeys( ctr ); for ( i=0; i<num_subkeys; i++ ) { pstr_sprintf( path, "%s%c%s", key, '/', regsubkey_ctr_specific_key( ctr, i ) ); if ( !(subkeys = TALLOC_ZERO_P( ctr, REGSUBKEY_CTR )) ) { DEBUG(0,("regdb_store_keys: talloc() failure!\n")); return False; } if ( regdb_fetch_keys( path, subkeys ) == -1 ) { /* create a record with 0 subkeys */ if ( !regdb_store_keys_internal( path, subkeys ) ) { DEBUG(0,("regdb_store_keys: Failed to store new record for key [%s}\n", path )); TALLOC_FREE( subkeys ); return False; } } TALLOC_FREE( subkeys ); } return True; }