static uint32_t spoolss_format_sd(smb_sd_t *sd) { smb_fssd_t fs_sd; acl_t *acl; uint32_t status = ERROR_SUCCESS; if (acl_fromtext("everyone@:full_set::allow", &acl) != 0) { smb_tracef("spoolss_format_sd: NOT_ENOUGH_MEMORY"); return (ERROR_NOT_ENOUGH_MEMORY); } smb_fssd_init(&fs_sd, SMB_ALL_SECINFO, SMB_FSSD_FLAGS_DIR); fs_sd.sd_uid = 0; fs_sd.sd_gid = 0; fs_sd.sd_zdacl = acl; fs_sd.sd_zsacl = NULL; status = smb_sd_fromfs(&fs_sd, sd); if (status != NT_STATUS_SUCCESS) { smb_tracef("spoolss_format_sd: %u", status); status = ERROR_ACCESS_DENIED; } smb_fssd_term(&fs_sd); return (status); }
void srvsvc_net_test(char *server, char *domain, char *netname) { smb_domainex_t di; srvsvc_server_info_t svinfo; (void) smb_tracef("%s %s %s", server, domain, netname); if (smb_domain_getinfo(&di)) { server = di.d_dc; domain = di.d_primary.di_nbname; } if (srvsvc_net_server_getinfo(server, domain, &svinfo) == 0) { smb_tracef("NetServerGetInfo: %s %s (%d.%d) id=%d type=0x%08x", svinfo.sv_name ? svinfo.sv_name : "NULL", svinfo.sv_comment ? svinfo.sv_comment : "NULL", svinfo.sv_version_major, svinfo.sv_version_minor, svinfo.sv_platform_id, svinfo.sv_type); free(svinfo.sv_name); free(svinfo.sv_comment); } (void) srvsvc_net_share_get_info(server, domain, netname); #if 0 /* * The NetSessionEnum server-side definition was updated. * Disabled until the client-side has been updated. */ (void) srvsvc_net_session_enum(server, domain, netname); #endif (void) srvsvc_net_connect_enum(server, domain, netname, 0); (void) srvsvc_net_connect_enum(server, domain, netname, 1); }
/* * Use the RPC context handle to find the fd and write the document content. */ static int spoolss_s_WritePrinter(void *arg, ndr_xa_t *mxa) { struct spoolss_WritePrinter *param = arg; int written = 0; ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; int spfd; if (ndr_hdlookup(mxa, id) == NULL) { param->written = 0; param->status = ERROR_INVALID_HANDLE; smb_tracef("spoolss_s_WritePrinter: invalid handle"); return (NDR_DRC_OK); } if ((spfd = spoolss_find_document(id)) < 0) { param->written = 0; param->status = ERROR_INVALID_HANDLE; smb_tracef("spoolss_s_WritePrinter: document not found"); return (NDR_DRC_OK); } written = write(spfd, param->pBuf, param->BufCount); if (written < param->BufCount) { smb_tracef("spoolss_s_WritePrinter: write failed"); param->written = 0; param->status = ERROR_CANTWRITE; return (NDR_DRC_OK); } param->written = written; param->status = ERROR_SUCCESS; return (NDR_DRC_OK); }
static int spoolss_getservername(char *name, size_t namelen) { char hostname[MAXHOSTNAMELEN]; char ipstr[INET6_ADDRSTRLEN]; smb_inaddr_t ipaddr; struct hostent *h; const char *p; int error; if (smb_gethostname(hostname, MAXHOSTNAMELEN, 0) != 0) { smb_tracef("spoolss_s_GetPrinter: gethostname failed"); return (-1); } if ((h = smb_gethostbyname(hostname, &error)) == NULL) { smb_tracef("spoolss_s_GetPrinter: gethostbyname failed: %d", error); return (-1); } bcopy(h->h_addr, &ipaddr, h->h_length); ipaddr.a_family = h->h_addrtype; freehostent(h); p = smb_inet_ntop(&ipaddr, ipstr, SMB_IPSTRLEN(ipaddr.a_family)); if (p == NULL) { smb_tracef("spoolss_s_GetPrinter: inet_ntop failed"); return (-1); } (void) snprintf(name, namelen, "\\\\%s", ipstr); return (0); }
/* * sam_create_account * * Create the specified domain account in the SAM database on the * domain controller. * * Account flags: * SAMR_AF_NORMAL_ACCOUNT * SAMR_AF_WORKSTATION_TRUST_ACCOUNT * SAMR_AF_SERVER_TRUST_ACCOUNT * * Returns NT status codes. */ DWORD sam_create_account(char *server, char *domain_name, char *account_name, DWORD account_flags) { mlsvc_handle_t samr_handle; mlsvc_handle_t domain_handle; mlsvc_handle_t user_handle; union samr_user_info sui; struct samr_sid *sid; DWORD rid; DWORD status; int rc; char user[SMB_USERNAME_MAXLEN]; smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); rc = samr_open(server, domain_name, user, SAM_CONNECT_CREATE_ACCOUNT, &samr_handle); if (rc != 0) { status = NT_STATUS_OPEN_FAILED; smb_tracef("SamCreateAccount[%s\\%s]: %s", domain_name, account_name, xlate_nt_status(status)); return (status); } sid = sam_get_domain_sid(&samr_handle, server, domain_name); status = samr_open_domain(&samr_handle, SAM_DOMAIN_CREATE_ACCOUNT, sid, &domain_handle); if (status == NT_STATUS_SUCCESS) { status = samr_create_user(&domain_handle, account_name, account_flags, &rid, &user_handle); if (status == NT_STATUS_SUCCESS) { (void) samr_query_user_info(&user_handle, SAMR_QUERY_USER_CONTROL_INFO, &sui); (void) samr_get_user_pwinfo(&user_handle); (void) samr_set_user_info(&user_handle); (void) samr_close_handle(&user_handle); } else if (status != NT_STATUS_USER_EXISTS) { smb_tracef("SamCreateAccount[%s]: %s", account_name, xlate_nt_status(status)); } (void) samr_close_handle(&domain_handle); } else { smb_tracef("SamCreateAccount[%s]: open domain failed", account_name); status = (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); } (void) samr_close_handle(&samr_handle); free(sid); return (status); }
void ndr_rpc_status(mlsvc_handle_t *handle, int opnum, DWORD status) { ndr_service_t *svc; char *name = "NDR RPC"; char *s = "unknown"; switch (NT_SC_SEVERITY(status)) { case NT_STATUS_SEVERITY_SUCCESS: s = "success"; break; case NT_STATUS_SEVERITY_INFORMATIONAL: s = "info"; break; case NT_STATUS_SEVERITY_WARNING: s = "warning"; break; case NT_STATUS_SEVERITY_ERROR: s = "error"; break; } if (handle) { svc = handle->clnt->binding->service; name = svc->name; } smb_tracef("%s[0x%02x]: %s: %s (0x%08x)", name, opnum, s, xlate_nt_status(status), status); }
/* * Lookup a sid and obtain the domain sid and account name. * This is a wrapper for the various lookup sid RPCs. */ uint32_t lsar_lookup_sids(mlsvc_handle_t *lsa_handle, smb_sid_t *sid, smb_account_t *account) { char sidbuf[SMB_SID_STRSZ]; uint32_t status; if (lsa_handle == NULL || sid == NULL || account == NULL) return (NT_STATUS_INVALID_PARAMETER); bzero(account, sizeof (smb_account_t)); bzero(sidbuf, SMB_SID_STRSZ); smb_sid_tostr(sid, sidbuf); smb_tracef("%s", sidbuf); if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) status = lsar_lookup_sids2(lsa_handle, (lsa_sid_t *)sid, account); else status = lsar_lookup_sids1(lsa_handle, (lsa_sid_t *)sid, account); if (status == NT_STATUS_SUCCESS) { if (!smb_account_validate(account)) { smb_account_free(account); status = NT_STATUS_NO_MEMORY; } else { smb_account_trace(account); } } return (status); }
static int spoolss_s_OpenPrinter(void *arg, ndr_xa_t *mxa) { struct spoolss_OpenPrinter *param = arg; char *name = (char *)param->printer_name; ndr_hdid_t *id; if (name != NULL && *name != '\0') { if (strspn(name, "\\") > 2) { bzero(¶m->handle, sizeof (spoolss_handle_t)); param->status = ERROR_INVALID_PRINTER_NAME; return (NDR_DRC_OK); } smb_tracef("spoolss_s_OpenPrinter: %s", name); } if ((id = ndr_hdalloc(mxa, NULL)) == NULL) { bzero(¶m->handle, sizeof (spoolss_handle_t)); param->status = ERROR_NOT_ENOUGH_MEMORY; return (NDR_DRC_OK); } bcopy(id, ¶m->handle, sizeof (spoolss_handle_t)); param->status = 0; return (NDR_DRC_OK); }
/* * This is a client side routine for NetSessionEnum. * NetSessionEnum requires administrator rights. */ int srvsvc_net_session_enum(char *server, char *domain, char *netname) { struct mslm_NetSessionEnum arg; mlsvc_handle_t handle; int rc; int opnum; struct mslm_infonres infonres; struct mslm_SESSION_INFO_1 *nsi1; int len; char user[SMB_USERNAME_MAXLEN]; if (netname == NULL) return (-1); smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); rc = srvsvc_open(server, domain, user, &handle); if (rc != 0) return (-1); opnum = SRVSVC_OPNUM_NetSessionEnum; bzero(&arg, sizeof (struct mslm_NetSessionEnum)); len = strlen(server) + 4; arg.servername = ndr_rpc_malloc(&handle, len); if (arg.servername == NULL) { srvsvc_close(&handle); return (-1); } (void) snprintf((char *)arg.servername, len, "\\\\%s", server); infonres.entriesread = 0; infonres.entries = 0; arg.level = 1; arg.result.level = 1; arg.result.bufptr.p = &infonres; arg.resume_handle = 0; arg.pref_max_len = 0xFFFFFFFF; rc = ndr_rpc_call(&handle, opnum, &arg); if ((rc != 0) || (arg.status != 0)) { srvsvc_close(&handle); return (-1); } /* Only the first session info is dereferenced. */ nsi1 = ((struct mslm_infonres *)arg.result.bufptr.p)->entries; smb_tracef("srvsvc switch_value=%d", arg.level); smb_tracef("srvsvc sesi1_cname=%s", nsi1->sesi1_cname); smb_tracef("srvsvc sesi1_uname=%s", nsi1->sesi1_uname); smb_tracef("srvsvc sesi1_nopens=%u", nsi1->sesi1_nopens); smb_tracef("srvsvc sesi1_time=%u", nsi1->sesi1_time); smb_tracef("srvsvc sesi1_itime=%u", nsi1->sesi1_itime); smb_tracef("srvsvc sesi1_uflags=%u", nsi1->sesi1_uflags); srvsvc_close(&handle); return (0); }
/* * * hexdump * * Simple hex dump display function. Displays nbytes of buffer in hex and * printable format. Non-printing characters are shown as '.'. It is safe * to pass a null pointer. Each line begins with the offset. If nbytes is * 0, the line will be blank except for the offset. Example output: * * 00000000 54 68 69 73 20 69 73 20 61 20 70 72 6F 67 72 61 This is a progra * 00000010 6D 20 74 65 73 74 2E 00 m test.. * */ void hexdump_offset(unsigned char *buffer, int nbytes, unsigned long *start) { static char *hex = "0123456789ABCDEF"; int i, count; int offset; unsigned char *p; char ascbuf[64]; char hexbuf[64]; char *ap = ascbuf; char *hp = hexbuf; if ((p = buffer) == NULL) return; offset = *start; *ap = '\0'; *hp = '\0'; count = 0; for (i = 0; i < nbytes; ++i) { if (i && (i % 16) == 0) { smb_tracef("%06X %s %s", offset, hexbuf, ascbuf); ap = ascbuf; hp = hexbuf; count = 0; offset += 16; } ap += sprintf(ap, "%c", (*p >= 0x20 && *p < 0x7F) ? *p : '.'); hp += sprintf(hp, " %c%c", hex[(*p >> 4) & 0x0F], hex[(*p & 0x0F)]); ++p; ++count; } if (count) { smb_tracef("%06X %-48s %s", offset, hexbuf, ascbuf); offset += count; } *start = offset; }
static void smb_account_trace(const smb_account_t *info) { char sidbuf[SMB_SID_STRSZ]; bzero(sidbuf, SMB_SID_STRSZ); smb_sid_tostr(info->a_sid, sidbuf); smb_tracef("%s %s %s %lu %s", info->a_domain, info->a_name, sidbuf, info->a_rid, smb_sid_type2str(info->a_type)); }
/* * samr_create_user * * Create a user in the domain specified by the domain handle. If this * call is successful, the server will return the RID for the user and * a user handle, which may be used to set or query the SAM. * * Observed status codes: * NT_STATUS_INVALID_PARAMETER * NT_STATUS_INVALID_ACCOUNT_NAME * NT_STATUS_ACCESS_DENIED * NT_STATUS_USER_EXISTS * * Returns 0 on success. Otherwise returns an NT status code. */ DWORD samr_create_user(mlsvc_handle_t *domain_handle, char *username, DWORD account_flags, DWORD *rid, mlsvc_handle_t *user_handle) { struct samr_CreateUser arg; ndr_heap_t *heap; int opnum; int rc; DWORD status = 0; if (ndr_is_null_handle(domain_handle) || username == NULL || rid == NULL) { return (NT_STATUS_INVALID_PARAMETER); } opnum = SAMR_OPNUM_CreateUser; bzero(&arg, sizeof (struct samr_CreateUser)); (void) memcpy(&arg.handle, &domain_handle->handle, sizeof (ndr_hdid_t)); heap = ndr_rpc_get_heap(domain_handle); ndr_heap_mkvcs(heap, username, (ndr_vcstr_t *)&arg.username); arg.account_flags = account_flags; arg.desired_access = 0xE00500B0; rc = ndr_rpc_call(domain_handle, opnum, &arg); if (rc != 0) { status = NT_STATUS_INVALID_PARAMETER; } else if (arg.status != 0) { status = NT_SC_VALUE(arg.status); if (status != NT_STATUS_USER_EXISTS) { smb_tracef("SamrCreateUser[%s]: %s", username, xlate_nt_status(status)); } } else { ndr_inherit_handle(user_handle, domain_handle); (void) memcpy(&user_handle->handle, &arg.user_handle, sizeof (ndr_hdid_t)); *rid = arg.rid; if (ndr_is_null_handle(user_handle)) status = NT_STATUS_INVALID_HANDLE; else status = 0; } ndr_rpc_release(domain_handle); return (status); }
/* * Synchronize the local system clock with the domain controller. */ void srvsvc_timesync(void) { smb_domainex_t di; struct timeval tv; struct tm tm; time_t tsecs; if (!smb_domain_getinfo(&di)) return; if (srvsvc_net_remote_tod(di.d_dc, di.d_primary.di_nbname, &tv, &tm) != 0) return; if (settimeofday(&tv, 0)) smb_tracef("unable to set system time"); tsecs = time(0); (void) localtime_r(&tsecs, &tm); smb_tracef("SrvsvcTimeSync %s", ctime((time_t *)&tv.tv_sec)); }
/* * Windows XP and 2000 use this mechanism to write spool files * Search the spooldoc list for a matching RPC handle and pass * the spool the file for printing. */ static int spoolss_s_EndDocPrinter(void *arg, ndr_xa_t *mxa) { struct spoolss_EndDocPrinter *param = arg; ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; smb_spooldoc_t *sp; if (ndr_hdlookup(mxa, id) == NULL) { smb_tracef("spoolss_s_EndDocPrinter: invalid handle"); param->status = ERROR_INVALID_HANDLE; return (NDR_DRC_OK); } param->status = ERROR_INVALID_HANDLE; (void) rw_wrlock(&spoolss_splist.sp_rwl); sp = list_head(&spoolss_splist.sp_list); while (sp != NULL) { if (!memcmp(id, &(sp->sd_handle), sizeof (ndr_hdid_t))) { spoolss_copyfile(&sp->sd_ipaddr, sp->sd_username, sp->sd_path, sp->sd_doc_name); (void) close(sp->sd_fd); list_remove(&spoolss_splist.sp_list, sp); free(sp); param->status = ERROR_SUCCESS; break; } sp = list_next(&spoolss_splist.sp_list, sp); } (void) rw_unlock(&spoolss_splist.sp_rwl); if (param->status != ERROR_SUCCESS) smb_tracef("spoolss_s_EndDocPrinter: document not found"); return (NDR_DRC_OK); }
int spoolss_s_GetPrinter(void *arg, ndr_xa_t *mxa) { struct spoolss_GetPrinter *param = arg; struct spoolss_GetPrinter0 *pinfo0; struct spoolss_GetPrinter1 *pinfo1; struct spoolss_GetPrinter2 *pinfo2; struct spoolss_DeviceMode *devmode2; ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; spoolss_sd_t secdesc; char server[MAXNAMELEN]; char printer[MAXNAMELEN]; DWORD status = ERROR_SUCCESS; char *wname; uint32_t offset; uint8_t *tmpbuf; if (ndr_hdlookup(mxa, id) == NULL) { status = ERROR_INVALID_HANDLE; goto error_out; } if (spoolss_getservername(server, MAXNAMELEN) != 0) { status = ERROR_INTERNAL_ERROR; goto error_out; } (void) snprintf(printer, MAXNAMELEN, "%s\\%s", server, SPOOLSS_PRINTER); switch (param->switch_value) { case 0: case 1: param->needed = 460; break; case 2: param->needed = 712; break; default: status = ERROR_INVALID_LEVEL; goto error_out; } if (param->BufCount < param->needed) { param->BufCount = 0; param->Buf = NULL; param->status = ERROR_INSUFFICIENT_BUFFER; return (NDR_DRC_OK); } if ((param->Buf = NDR_MALLOC(mxa, param->BufCount)) == NULL) { status = ERROR_NOT_ENOUGH_MEMORY; goto error_out; } bzero(param->Buf, param->BufCount); wname = (char *)param->Buf; offset = param->needed; switch (param->switch_value) { case 0: /*LINTED E_BAD_PTR_CAST_ALIGN*/ pinfo0 = (struct spoolss_GetPrinter0 *)param->Buf; smb_rpc_off(wname, server, &offset, &pinfo0->servername); smb_rpc_off(wname, printer, &offset, &pinfo0->printername); pinfo0->cjobs = 0; pinfo0->total_jobs = 6; pinfo0->total_bytes = 1040771; pinfo0->time0 = 0; pinfo0->time1 = 0; pinfo0->time2 = 3; pinfo0->time3 = 0; pinfo0->global_counter = 2162710; pinfo0->total_pages = 21495865; pinfo0->version = 10; pinfo0->session_counter = 1; pinfo0->job_error = 0x6; pinfo0->change_id = 0x1; pinfo0->status = 0; pinfo0->c_setprinter = 0; break; case 1: /*LINTED E_BAD_PTR_CAST_ALIGN*/ pinfo1 = (struct spoolss_GetPrinter1 *)param->Buf; pinfo1->flags = PRINTER_ENUM_ICON8; smb_rpc_off(wname, printer, &offset, &pinfo1->flags); smb_rpc_off(wname, printer, &offset, &pinfo1->description); smb_rpc_off(wname, printer, &offset, &pinfo1->comment); break; case 2: /*LINTED E_BAD_PTR_CAST_ALIGN*/ pinfo2 = (struct spoolss_GetPrinter2 *)param->Buf; smb_rpc_off(wname, server, &offset, &pinfo2->servername); smb_rpc_off(wname, printer, &offset, &pinfo2->printername); smb_rpc_off(wname, SPOOLSS_PRINTER, &offset, &pinfo2->sharename); smb_rpc_off(wname, "CIFS Printer Port", &offset, &pinfo2->portname); smb_rpc_off(wname, "", &offset, &pinfo2->drivername); smb_rpc_off(wname, SPOOLSS_PRINTER, &offset, &pinfo2->comment); smb_rpc_off(wname, "farside", &offset, &pinfo2->location); offset -= sizeof (struct spoolss_DeviceMode); pinfo2->devmode = offset; /*LINTED E_BAD_PTR_CAST_ALIGN*/ devmode2 = (struct spoolss_DeviceMode *)(param->Buf + offset); smb_rpc_off(wname, "farside", &offset, &pinfo2->sepfile); smb_rpc_off(wname, "winprint", &offset, &pinfo2->printprocessor); smb_rpc_off(wname, "RAW", &offset, &pinfo2->datatype); smb_rpc_off(wname, "", &offset, &pinfo2->parameters); status = spoolss_make_sd(mxa, &secdesc); if (status == ERROR_SUCCESS) { offset -= secdesc.sd_size; pinfo2->secdesc = offset; tmpbuf = (uint8_t *)(param->Buf + offset); bcopy(secdesc.sd_buf, tmpbuf, secdesc.sd_size); } pinfo2->attributes = 0x00001048; pinfo2->status = 0x00000000; pinfo2->starttime = 0; pinfo2->untiltime = 0; pinfo2->cjobs = 0; pinfo2->averageppm = 0; pinfo2->defaultpriority = 0; /*LINTED E_BAD_PTR_CAST_ALIGN*/ (void) smb_mbstowcs((smb_wchar_t *)devmode2->devicename, printer, 32); devmode2->specversion = 0x0401; devmode2->driverversion = 1024; devmode2->size = 220; devmode2->driverextra_length = 0; devmode2->fields = 0x00014713; devmode2->orientation = 1; devmode2->papersize = 1; devmode2->paperlength = 0; devmode2->paperwidth = 0; devmode2->scale = 100; devmode2->copies = 1; devmode2->defaultsource = 15; devmode2->printquality = 65532; devmode2->color = 1; devmode2->duplex = 1; devmode2->yresolution = 1; devmode2->ttoption = 1; devmode2->collate = 0; /*LINTED E_BAD_PTR_CAST_ALIGN*/ (void) smb_mbstowcs((smb_wchar_t *)devmode2->formname, "Letter", 32); devmode2->logpixels = 0; devmode2->bitsperpel = 0; devmode2->pelswidth = 0; devmode2->pelsheight = 0; devmode2->displayflags = 0; devmode2->displayfrequency = 0; devmode2->icmmethod = 0; devmode2->icmintent = 0; devmode2->mediatype = 0; devmode2->dithertype = 0; devmode2->reserved1 = 0; devmode2->reserved2 = 0; devmode2->panningwidth = 0; devmode2->panningheight = 0; break; default: break; } param->status = status; return (NDR_DRC_OK); error_out: smb_tracef("spoolss_s_GetPrinter: error %u", status); bzero(param, sizeof (struct spoolss_GetPrinter)); param->status = status; return (NDR_DRC_OK); }
/* * Windows XP and 2000 use this mechanism to write spool files. * Create a spool file fd to be used by spoolss_s_WritePrinter * and add it to the tail of the spool list. */ static int spoolss_s_StartDocPrinter(void *arg, ndr_xa_t *mxa) { struct spoolss_StartDocPrinter *param = arg; ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; smb_spooldoc_t *spfile; spoolss_DocInfo_t *docinfo; char g_path[MAXPATHLEN]; smb_share_t si; int rc; int fd; if (ndr_hdlookup(mxa, id) == NULL) { smb_tracef("spoolss_s_StartDocPrinter: invalid handle"); param->status = ERROR_INVALID_HANDLE; return (NDR_DRC_OK); } if ((docinfo = param->dinfo.DocInfoContainer) == NULL) { param->status = ERROR_INVALID_PARAMETER; return (NDR_DRC_OK); } if ((rc = smb_shr_get(SMB_SHARE_PRINT, &si)) != NERR_Success) { smb_tracef("spoolss_s_StartDocPrinter: %s error=%d", SMB_SHARE_PRINT, rc); param->status = rc; return (NDR_DRC_OK); } if ((spfile = calloc(1, sizeof (smb_spooldoc_t))) == NULL) { param->status = ERROR_NOT_ENOUGH_MEMORY; return (NDR_DRC_OK); } if (docinfo->doc_name != NULL) (void) strlcpy(spfile->sd_doc_name, (char *)docinfo->doc_name, MAXNAMELEN); else (void) strlcpy(spfile->sd_doc_name, "document", MAXNAMELEN); if (docinfo->printer_name != NULL) (void) strlcpy(spfile->sd_printer_name, (char *)docinfo->printer_name, MAXPATHLEN); else (void) strlcpy(spfile->sd_printer_name, "printer", MAXPATHLEN); spfile->sd_ipaddr = mxa->pipe->np_user->ui_ipaddr; (void) strlcpy((char *)spfile->sd_username, mxa->pipe->np_user->ui_account, MAXNAMELEN); (void) memcpy(&spfile->sd_handle, ¶m->handle, sizeof (ndr_hdid_t)); /* * write temporary spool file to print$ */ (void) snprintf(g_path, MAXPATHLEN, "%s/%s%d", si.shr_path, spfile->sd_username, spoolss_cnt); atomic_inc_32(&spoolss_cnt); fd = open(g_path, O_CREAT | O_RDWR, 0600); if (fd == -1) { smb_tracef("spoolss_s_StartDocPrinter: %s: %s", g_path, strerror(errno)); param->status = ERROR_OPEN_FAILED; free(spfile); } else { (void) strlcpy((char *)spfile->sd_path, g_path, MAXPATHLEN); spfile->sd_fd = (uint16_t)fd; /* * Add the document to the spool list. */ (void) rw_wrlock(&spoolss_splist.sp_rwl); list_insert_tail(&spoolss_splist.sp_list, spfile); spoolss_splist.sp_cnt++; (void) rw_unlock(&spoolss_splist.sp_rwl); /* * JobId isn't used now, but if printQ management is added * this will have to be incremented per job submitted. */ param->JobId = 46; param->status = ERROR_SUCCESS; } return (NDR_DRC_OK); }
/* * This is a client side routine for NetShareGetInfo. * Levels 0 and 1 work with an anonymous connection but * level 2 requires administrator access. */ int srvsvc_net_share_get_info(char *server, char *domain, char *netname) { struct mlsm_NetShareGetInfo arg; mlsvc_handle_t handle; int rc; int opnum; struct mslm_NetShareInfo_0 *info0; struct mslm_NetShareInfo_1 *info1; struct mslm_NetShareInfo_2 *info2; int len; char user[SMB_USERNAME_MAXLEN]; if (netname == NULL) return (-1); if (srvsvc_info_level == 2) smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); if (srvsvc_open(server, domain, user, &handle) != 0) return (-1); opnum = SRVSVC_OPNUM_NetShareGetInfo; bzero(&arg, sizeof (struct mlsm_NetShareGetInfo)); len = strlen(server) + 4; arg.servername = ndr_rpc_malloc(&handle, len); if (arg.servername == NULL) { srvsvc_close(&handle); return (-1); } (void) snprintf((char *)arg.servername, len, "\\\\%s", server); arg.netname = (LPTSTR)netname; arg.level = srvsvc_info_level; /* share information level */ rc = ndr_rpc_call(&handle, opnum, &arg); if ((rc != 0) || (arg.status != 0)) { srvsvc_close(&handle); return (-1); } switch (arg.result.switch_value) { case 0: info0 = arg.result.ru.info0; smb_tracef("srvsvc shi0_netname=%s", info0->shi0_netname); break; case 1: info1 = arg.result.ru.info1; smb_tracef("srvsvc shi1_netname=%s", info1->shi1_netname); smb_tracef("srvsvc shi1_type=%u", info1->shi1_type); if (info1->shi1_comment) smb_tracef("srvsvc shi1_comment=%s", info1->shi1_comment); break; case 2: info2 = arg.result.ru.info2; smb_tracef("srvsvc shi2_netname=%s", info2->shi2_netname); smb_tracef("srvsvc shi2_type=%u", info2->shi2_type); if (info2->shi2_comment) smb_tracef("srvsvc shi2_comment=%s", info2->shi2_comment); smb_tracef("srvsvc shi2_perms=%d", info2->shi2_permissions); smb_tracef("srvsvc shi2_max_use=%d", info2->shi2_max_uses); smb_tracef("srvsvc shi2_cur_use=%d", info2->shi2_current_uses); if (info2->shi2_path) smb_tracef("srvsvc shi2_path=%s", info2->shi2_path); if (info2->shi2_passwd) smb_tracef("srvsvc shi2_passwd=%s", info2->shi2_passwd); break; default: smb_tracef("srvsvc: unknown level"); break; } srvsvc_close(&handle); return (0); }
/* * This is a client side routine for NetConnectEnum. * NetConnectEnum requires administrator rights. * Level 0 and level 1 requests are supported. */ int srvsvc_net_connect_enum(char *server, char *domain, char *netname, int level) { struct mslm_NetConnectEnum arg; mlsvc_handle_t handle; int rc; int opnum; struct mslm_NetConnectInfo1 info1; struct mslm_NetConnectInfo0 info0; struct mslm_NetConnectInfoBuf1 *cib1; int len; char user[SMB_USERNAME_MAXLEN]; if (netname == NULL) return (-1); smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); rc = srvsvc_open(server, domain, user, &handle); if (rc != 0) return (-1); opnum = SRVSVC_OPNUM_NetConnectEnum; bzero(&arg, sizeof (struct mslm_NetConnectEnum)); len = strlen(server) + 4; arg.servername = ndr_rpc_malloc(&handle, len); if (arg.servername == NULL) { srvsvc_close(&handle); return (-1); } (void) snprintf((char *)arg.servername, len, "\\\\%s", server); arg.qualifier = (LPTSTR)netname; switch (level) { case 0: arg.info.level = 0; arg.info.switch_value = 0; arg.info.ru.info0 = &info0; info0.entries_read = 0; info0.ci0 = 0; break; case 1: arg.info.level = 1; arg.info.switch_value = 1; arg.info.ru.info1 = &info1; info1.entries_read = 0; info1.ci1 = 0; break; default: srvsvc_close(&handle); return (-1); } arg.resume_handle = 0; arg.pref_max_len = 0xFFFFFFFF; rc = ndr_rpc_call(&handle, opnum, &arg); if ((rc != 0) || (arg.status != 0)) { srvsvc_close(&handle); return (-1); } smb_tracef("srvsvc switch_value=%d", arg.info.switch_value); switch (level) { case 0: if (arg.info.ru.info0 && arg.info.ru.info0->ci0) { smb_tracef("srvsvc coni0_id=%x", arg.info.ru.info0->ci0->coni0_id); } break; case 1: if (arg.info.ru.info1 && arg.info.ru.info1->ci1) { cib1 = arg.info.ru.info1->ci1; smb_tracef("srvsvc coni_uname=%s", cib1->coni1_username ? (char *)cib1->coni1_username : "******"); smb_tracef("srvsvc coni1_netname=%s", cib1->coni1_netname ? (char *)cib1->coni1_netname : "(null)"); smb_tracef("srvsvc coni1_nopens=%u", cib1->coni1_num_opens); smb_tracef("srvsvc coni1_time=%u", cib1->coni1_time); smb_tracef("srvsvc coni1_num_users=%u", cib1->coni1_num_users); } break; default: smb_tracef("srvsvc: unknown level"); break; } srvsvc_close(&handle); return (0); }
/* * Trace the given DFS info structure */ void dfs_info_trace(const char *msg, dfs_info_t *info) { dfs_target_t *t; int i; smb_tracef("%s", msg); if (info == NULL) return; smb_tracef("UNC\t%s", info->i_uncpath); smb_tracef("comment\t%s", info->i_comment); smb_tracef("GUID\t%s", info->i_guid); smb_tracef("state\t%X", info->i_state); smb_tracef("timeout\t%d", info->i_timeout); smb_tracef("props\t%X", info->i_propflags); smb_tracef("# targets\t%X", info->i_ntargets); if (info->i_targets == NULL) return; for (i = 0, t = info->i_targets; i < info->i_ntargets; i++, t++) { smb_tracef("[%d] \\\\%s\\%s", i, t->t_server, t->t_share); smb_tracef("[%d] state\t%X", i, t->t_state); smb_tracef("[%d] priority\t%d:%d", i, t->t_priority.p_class, t->t_priority.p_rank); } }