static uint32_t spoolss_make_sd(ndr_xa_t *mxa, spoolss_sd_t *secdesc) { smb_sd_t sd; uint8_t *sd_buf; uint32_t sd_len; uint32_t status; bzero(&sd, sizeof (smb_sd_t)); if ((status = spoolss_format_sd(&sd)) != ERROR_SUCCESS) return (status); sd_len = smb_sd_len(&sd, SMB_ALL_SECINFO); if ((sd_buf = NDR_MALLOC(mxa, sd_len)) == NULL) return (ERROR_NOT_ENOUGH_MEMORY); secdesc->sd_buf = sd_buf; secdesc->sd_size = sd_len; status = srvsvc_sd_set_relative(&sd, sd_buf); smb_sd_term(&sd); return (status); }
/* * lsarpc_s_QueryInfoPolicy * * This is the server side function for handling LSA information policy * queries. Currently, we only support primary domain and account * domain queries. This is just a front end to switch on the request * and hand it off to the appropriate function to actually deal with * obtaining and building the response. */ static int lsarpc_s_QueryInfoPolicy(void *arg, ndr_xa_t *mxa) { struct mslsa_QueryInfoPolicy *param = arg; union mslsa_PolicyInfoResUnion *ru = ¶m->ru; int security_mode; DWORD status; param->switch_value = param->info_class; switch (param->info_class) { case MSLSA_POLICY_AUDIT_EVENTS_INFO: ru->audit_events.enabled = 0; ru->audit_events.count = 1; ru->audit_events.settings = NDR_MALLOC(mxa, sizeof (DWORD)); bzero(ru->audit_events.settings, sizeof (DWORD)); status = NT_STATUS_SUCCESS; break; case MSLSA_POLICY_PRIMARY_DOMAIN_INFO: status = lsarpc_s_PrimaryDomainInfo(&ru->pd_info, mxa); break; case MSLSA_POLICY_ACCOUNT_DOMAIN_INFO: status = lsarpc_s_AccountDomainInfo(&ru->ad_info, mxa); break; case MSLSA_POLICY_SERVER_ROLE_INFO: security_mode = smb_config_get_secmode(); if (security_mode == SMB_SECMODE_DOMAIN) ru->server_role.role = LSA_ROLE_MEMBER_SERVER; else ru->server_role.role = LSA_ROLE_STANDALONE_SERVER; ru->server_role.pad = 0; status = NT_STATUS_SUCCESS; break; default: bzero(param, sizeof (struct mslsa_QueryInfoPolicy)); param->status = NT_SC_ERROR(NT_STATUS_INVALID_INFO_CLASS); return (NDR_DRC_OK); } if (status != NT_STATUS_SUCCESS) param->status = NT_SC_ERROR(status); else param->status = NT_STATUS_SUCCESS; param->address = (DWORD)(uintptr_t)ru; 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); }
/* * GetPrinterData is used t obtain values from the registry for a * printer or a print server. See [MS-RPRN] for value descriptions. * The registry returns ERROR_FILE_NOT_FOUND for unknown keys. */ static int spoolss_s_GetPrinterData(void *arg, ndr_xa_t *mxa) { static spoolss_winreg_t reg[] = { { "ChangeId", 0x0050acf2 }, { "W3SvcInstalled", 0x00000000 }, { "BeepEnabled", 0x00000000 }, { "EventLog", 0x0000001f }, { "NetPopup", 0x00000000 }, { "NetPopupToComputer", 0x00000000 }, { "MajorVersion", 0x00000003 }, { "MinorVersion", 0x00000000 }, { "DsPresent", 0x00000000 } }; struct spoolss_GetPrinterData *param = arg; char *name = (char *)param->pValueName; char buf[MAXPATHLEN]; static uint8_t reserved_buf[4]; spoolss_winreg_t *rp; smb_share_t si; smb_version_t *osversion; struct utsname sysname; smb_wchar_t *wcs; uint32_t value; uint32_t status; int wcslen; int i; if (name == NULL || *name == '\0') { status = ERROR_FILE_NOT_FOUND; goto report_error; } for (i = 0; i < sizeof (reg) / sizeof (reg[0]); ++i) { param->pType = WINREG_DWORD; param->Needed = sizeof (uint32_t); rp = ®[i]; if (strcasecmp(name, rp->name) != 0) continue; if (param->Size < sizeof (uint32_t)) { param->Size = 0; goto need_more_data; } if ((param->Buf = NDR_NEW(mxa, uint32_t)) == NULL) { status = ERROR_NOT_ENOUGH_MEMORY; goto report_error; } value = rp->value; if ((strcasecmp(name, "DsPresent") == 0) && (smb_config_get_secmode() == SMB_SECMODE_DOMAIN)) value = 0x00000001; bcopy(&value, param->Buf, sizeof (uint32_t)); param->Size = sizeof (uint32_t); param->status = ERROR_SUCCESS; return (NDR_DRC_OK); } if (strcasecmp(name, "OSVersion") == 0) { param->pType = WINREG_BINARY; param->Needed = sizeof (smb_version_t); if (param->Size < sizeof (smb_version_t)) { param->Size = sizeof (smb_version_t); goto need_more_data; } if ((osversion = NDR_NEW(mxa, smb_version_t)) == NULL) { status = ERROR_NOT_ENOUGH_MEMORY; goto report_error; } smb_config_get_version(osversion); param->Buf = (uint8_t *)osversion; param->status = ERROR_SUCCESS; return (NDR_DRC_OK); } if (strcasecmp(name, "DNSMachineName") == 0) { param->pType = WINREG_SZ; buf[0] = '\0'; (void) smb_getfqhostname(buf, MAXHOSTNAMELEN); goto encode_string; } if (strcasecmp(name, "DefaultSpoolDirectory") == 0) { param->pType = WINREG_SZ; buf[0] = '\0'; if (smb_shr_get(SMB_SHARE_PRINT, &si) != NERR_Success) { status = ERROR_FILE_NOT_FOUND; goto report_error; } (void) snprintf(buf, MAXPATHLEN, "C:/%s", si.shr_path); (void) strcanon(buf, "/\\"); (void) strsubst(buf, '/', '\\'); goto encode_string; } if (strcasecmp(name, "Architecture") == 0) { param->pType = WINREG_SZ; if (uname(&sysname) < 0) (void) strlcpy(buf, "Solaris", MAXPATHLEN); else (void) snprintf(buf, MAXPATHLEN, "%s %s", sysname.sysname, sysname.machine); goto encode_string; } status = ERROR_FILE_NOT_FOUND; report_error: bzero(param, sizeof (struct spoolss_GetPrinterData)); param->Buf = reserved_buf; param->status = status; return (NDR_DRC_OK); encode_string: wcslen = smb_wcequiv_strlen(buf) + sizeof (smb_wchar_t); if (param->Size < wcslen) { param->Needed = wcslen; goto need_more_data; } if ((wcs = NDR_MALLOC(mxa, wcslen)) == NULL) { status = ERROR_NOT_ENOUGH_MEMORY; goto report_error; } (void) ndr_mbstowcs(NULL, wcs, buf, wcslen); param->Buf = (uint8_t *)wcs; param->Needed = wcslen; param->status = ERROR_SUCCESS; return (NDR_DRC_OK); need_more_data: param->Size = 0; param->Buf = reserved_buf; param->status = ERROR_MORE_DATA; return (NDR_DRC_OK); }