/* * 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_s_DeleteForm(void *arg, ndr_xa_t *mxa) { struct spoolss_DeleteForm *param = arg; ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; if (ndr_hdlookup(mxa, id) == NULL) { bzero(param, sizeof (struct spoolss_DeleteForm)); param->status = ERROR_INVALID_HANDLE; return (NDR_DRC_OK); } bzero(param, sizeof (struct spoolss_DeleteForm)); param->status = ERROR_SUCCESS; return (NDR_DRC_OK); }
static int spoolss_s_ClosePrinter(void *arg, ndr_xa_t *mxa) { struct spoolss_ClosePrinter *param = arg; ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; ndr_handle_t *hd; if ((hd = ndr_hdlookup(mxa, id)) != NULL) { free(hd->nh_data); hd->nh_data = NULL; } ndr_hdfree(mxa, id); bzero(¶m->result_handle, sizeof (spoolss_handle_t)); param->status = ERROR_SUCCESS; return (NDR_DRC_OK); }
static int lsarpc_s_OpenSecret(void *arg, ndr_xa_t *mxa) { struct mslsa_OpenSecret *param = arg; ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; ndr_handle_t *hd; hd = ndr_hdlookup(mxa, id); if ((hd == NULL) || (hd->nh_data != &lsarpc_key_domain)) { bzero(param, sizeof (struct mslsa_OpenAccount)); param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); return (NDR_DRC_OK); } bzero(¶m->secret_handle, sizeof (mslsa_handle_t)); param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); return (NDR_DRC_OK); }
/* * 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); }
/* * lsarpc_s_OpenAccount * * This is a request to open an account handle. */ static int lsarpc_s_OpenAccount(void *arg, ndr_xa_t *mxa) { struct mslsa_OpenAccount *param = arg; ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; ndr_handle_t *hd; hd = ndr_hdlookup(mxa, id); if ((hd == NULL) || (hd->nh_data != &lsarpc_key_domain)) { bzero(param, sizeof (struct mslsa_OpenAccount)); param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); return (NDR_DRC_OK); } if ((id = ndr_hdalloc(mxa, &lsarpc_key_account)) != NULL) { bcopy(id, ¶m->account_handle, sizeof (mslsa_handle_t)); param->status = NT_STATUS_SUCCESS; } else { bzero(¶m->account_handle, sizeof (mslsa_handle_t)); param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); } 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); }