diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/rpc_server/srv_spoolss_util.c | 337 | ||||
-rw-r--r-- | source3/rpc_server/srv_spoolss_util.h | 4 |
2 files changed, 341 insertions, 0 deletions
diff --git a/source3/rpc_server/srv_spoolss_util.c b/source3/rpc_server/srv_spoolss_util.c index 4b2bab2876..df34dea07f 100644 --- a/source3/rpc_server/srv_spoolss_util.c +++ b/source3/rpc_server/srv_spoolss_util.c @@ -189,6 +189,149 @@ static uint32_t winreg_printer_rev_changeid(void) #endif } +static struct spoolss_security_descriptor *winreg_printer_create_default_secdesc(TALLOC_CTX *ctx) +{ + SEC_ACE ace[5]; /* max number of ace entries */ + int i = 0; + uint32_t sa; + SEC_ACL *psa = NULL; + SEC_DESC *psd = NULL; + DOM_SID adm_sid; + size_t sd_size; + + /* Create an ACE where Everyone is allowed to print */ + + sa = PRINTER_ACE_PRINT; + init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, + sa, SEC_ACE_FLAG_CONTAINER_INHERIT); + + /* Add the domain admins group if we are a DC */ + + if ( IS_DC ) { + DOM_SID domadmins_sid; + + sid_compose(&domadmins_sid, get_global_sam_sid(), + DOMAIN_GROUP_RID_ADMINS); + + sa = PRINTER_ACE_FULL_CONTROL; + init_sec_ace(&ace[i++], &domadmins_sid, + SEC_ACE_TYPE_ACCESS_ALLOWED, sa, + SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY); + init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, + sa, SEC_ACE_FLAG_CONTAINER_INHERIT); + } + else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) { + sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN); + + sa = PRINTER_ACE_FULL_CONTROL; + init_sec_ace(&ace[i++], &adm_sid, + SEC_ACE_TYPE_ACCESS_ALLOWED, sa, + SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY); + init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, + sa, SEC_ACE_FLAG_CONTAINER_INHERIT); + } + + /* add BUILTIN\Administrators as FULL CONTROL */ + + sa = PRINTER_ACE_FULL_CONTROL; + init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, + SEC_ACE_TYPE_ACCESS_ALLOWED, sa, + SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY); + init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, + SEC_ACE_TYPE_ACCESS_ALLOWED, + sa, SEC_ACE_FLAG_CONTAINER_INHERIT); + + /* Make the security descriptor owned by the BUILTIN\Administrators */ + + /* The ACL revision number in rpc_secdesc.h differs from the one + created by NT when setting ACE entries in printer + descriptors. NT4 complains about the property being edited by a + NT5 machine. */ + + if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) { + psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, + &global_sid_Builtin_Administrators, + &global_sid_Builtin_Administrators, + NULL, psa, &sd_size); + } + + if (!psd) { + DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n")); + return NULL; + } + + DEBUG(4,("construct_default_printer_sdb: size = %u.\n", + (unsigned int)sd_size)); + + return psd; +} + +static struct spoolss_DeviceMode *winreg_printer_create_default_devmode(TALLOC_CTX *mem_ctx, + const char *default_devicename) +{ + char adevice[MAXDEVICENAME]; + struct spoolss_DeviceMode *devmode; + + devmode = talloc_zero(mem_ctx, struct spoolss_DeviceMode); + if (devmode == NULL) { + return NULL; + } + + slprintf(adevice, sizeof(adevice), "%s", default_devicename); + devmode->devicename = talloc_strdup(mem_ctx, adevice); + if (devmode->devicename == NULL) { + return NULL; + } + + devmode->formname = "Letter"; + + devmode->specversion = DMSPEC_NT4_AND_ABOVE; + devmode->driverversion = 0x0400; + devmode->size = 0x00DC; + devmode->__driverextra_length = 0; + devmode->fields = DEVMODE_FORMNAME | + DEVMODE_TTOPTION | + DEVMODE_PRINTQUALITY | + DEVMODE_DEFAULTSOURCE | + DEVMODE_COPIES | + DEVMODE_SCALE | + DEVMODE_PAPERSIZE | + DEVMODE_ORIENTATION; + devmode->orientation = DMORIENT_PORTRAIT; + devmode->papersize = DMPAPER_LETTER; + devmode->paperlength = 0; + devmode->paperwidth = 0; + devmode->scale = 0x64; + devmode->copies = 1; + devmode->defaultsource = DMBIN_FORMSOURCE; + devmode->printquality = DMRES_HIGH; /* 0x0258 */ + devmode->color = DMRES_MONOCHROME; + devmode->duplex = DMDUP_SIMPLEX; + devmode->yresolution = 0; + devmode->ttoption = DMTT_SUBDEV; + devmode->collate = DMCOLLATE_FALSE; + devmode->icmmethod = 0; + devmode->icmintent = 0; + devmode->mediatype = 0; + devmode->dithertype = 0; + + devmode->logpixels = 0; + devmode->bitsperpel = 0; + devmode->pelswidth = 0; + devmode->pelsheight = 0; + devmode->displayflags = 0; + devmode->displayfrequency = 0; + devmode->reserved1 = 0; + devmode->reserved2 = 0; + devmode->panningwidth = 0; + devmode->panningheight = 0; + + devmode->driverextra_data.data = NULL; + devmode->driverextra_data.length = 0; + + return devmode; +} + /** * @internal * @@ -1210,6 +1353,200 @@ static WERROR winreg_printer_ver_to_dword(const char *str, uint64_t *data) Public winreg function for spoolss ********************************************************************/ +WERROR winreg_create_printer(TALLOC_CTX *mem_ctx, + struct auth_serversupplied_info *server_info, + const char *sharename) +{ + uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + struct rpc_pipe_client *winreg_pipe = NULL; + struct policy_handle hive_hnd, key_hnd; + struct spoolss_SetPrinterInfo2 *info2; + struct spoolss_DeviceMode *devmode; + struct security_descriptor *secdesc; + struct winreg_String wkey, wkeyclass; + const char *path; + const char *subkeys[] = { "DsDriver", "DsSpooler", "PrinterDriverData" }; + uint32_t i, count = ARRAY_SIZE(subkeys); + int snum = lp_servicenumber(sharename); + uint32_t info2_mask = 0; + WERROR result = WERR_OK; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(mem_ctx); + if (tmp_ctx == NULL) { + return WERR_NOMEM; + } + + path = winreg_printer_data_keyname(tmp_ctx, sharename); + if (path == NULL) { + TALLOC_FREE(tmp_ctx); + return WERR_NOMEM; + } + + ZERO_STRUCT(hive_hnd); + ZERO_STRUCT(key_hnd); + + result = winreg_printer_openkey(tmp_ctx, + server_info, + &winreg_pipe, + path, + "", + false, + access_mask, + &hive_hnd, + &key_hnd); + if (W_ERROR_IS_OK(result)) { + DEBUG(2, ("winreg_create_printer: Skipping, %s already exists\n", path)); + goto done; + } else if (W_ERROR_EQUAL(result, WERR_BADFILE)) { + DEBUG(2, ("winreg_create_printer: Creating default values in %s\n", path)); + } else if (!W_ERROR_IS_OK(result)) { + DEBUG(0, ("winreg_create_printer: Could not open key %s: %s\n", + path, win_errstr(result))); + goto done; + } + + /* Create the main key */ + result = winreg_printer_openkey(tmp_ctx, + server_info, + &winreg_pipe, + path, + "", + true, + access_mask, + &hive_hnd, + &key_hnd); + if (!W_ERROR_IS_OK(result)) { + DEBUG(0, ("winreg_create_printer_keys: Could not create key %s: %s\n", + path, win_errstr(result))); + goto done; + } + + if (is_valid_policy_hnd(&key_hnd)) { + rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL); + } + + /* Create subkeys */ + for (i = 0; i < count; i++) { + NTSTATUS status; + enum winreg_CreateAction action = REG_ACTION_NONE; + + ZERO_STRUCT(key_hnd); + ZERO_STRUCT(wkey); + + wkey.name = talloc_asprintf(tmp_ctx, "%s\\%s", path, subkeys[i]); + if (wkey.name == NULL) { + result = WERR_NOMEM; + goto done; + } + + ZERO_STRUCT(wkeyclass); + wkeyclass.name = ""; + + status = rpccli_winreg_CreateKey(winreg_pipe, + tmp_ctx, + &hive_hnd, + wkey, + wkeyclass, + 0, + access_mask, + NULL, + &key_hnd, + &action, + &result); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("winreg_create_printer_keys: Could not create key %s: %s\n", + wkey.name, win_errstr(result))); + if (!W_ERROR_IS_OK(result)) { + result = ntstatus_to_werror(status); + } + goto done; + } + + if (is_valid_policy_hnd(&key_hnd)) { + rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL); + } + } + info2 = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2); + if (info2 == NULL) { + result = WERR_NOMEM; + goto done; + } + + info2->printername = sharename; + info2_mask |= SPOOLSS_PRINTER_INFO_PRINTERNAME; + + info2->sharename = sharename; + info2_mask |= SPOOLSS_PRINTER_INFO_SHARENAME; + + info2->portname = SAMBA_PRINTER_PORT_NAME; + info2_mask |= SPOOLSS_PRINTER_INFO_PORTNAME; + + info2->printprocessor = "winprint"; + info2_mask |= SPOOLSS_PRINTER_INFO_PRINTPROCESSOR; + + info2->datatype = "RAW"; + info2_mask |= SPOOLSS_PRINTER_INFO_DATATYPE; + + info2->comment = ""; + info2_mask |= SPOOLSS_PRINTER_INFO_COMMENT; + + info2->attributes = PRINTER_ATTRIBUTE_SAMBA; + info2_mask |= SPOOLSS_PRINTER_INFO_ATTRIBUTES; + + info2->starttime = 0; /* Minutes since 12:00am GMT */ + info2_mask |= SPOOLSS_PRINTER_INFO_STARTTIME; + + info2->untiltime = 0; /* Minutes since 12:00am GMT */ + info2_mask |= SPOOLSS_PRINTER_INFO_UNTILTIME; + + info2->priority = 1; + info2_mask |= SPOOLSS_PRINTER_INFO_PRIORITY; + + info2->defaultpriority = 1; + info2_mask |= SPOOLSS_PRINTER_INFO_DEFAULTPRIORITY; + + /* info2->setuptime = (uint32_t) time(NULL); */ + + if (lp_default_devmode(snum)) { + devmode = winreg_printer_create_default_devmode(tmp_ctx, + info2->printername); + if (devmode == NULL) { + result = WERR_NOMEM; + goto done; + } + + info2_mask |= SPOOLSS_PRINTER_INFO_DEVMODE; + } + + secdesc = winreg_printer_create_default_secdesc(tmp_ctx); + if (secdesc == NULL) { + result = WERR_NOMEM; + goto done; + } + info2_mask |= SPOOLSS_PRINTER_INFO_SECDESC; + + result = winreg_update_printer(tmp_ctx, + server_info, + info2_mask, + info2, + devmode, + secdesc); + +done: + if (winreg_pipe != NULL) { + if (is_valid_policy_hnd(&key_hnd)) { + rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &key_hnd, NULL); + } + if (is_valid_policy_hnd(&hive_hnd)) { + rpccli_winreg_CloseKey(winreg_pipe, tmp_ctx, &hive_hnd, NULL); + } + } + + talloc_free(tmp_ctx); + return result; +} + WERROR winreg_update_printer(TALLOC_CTX *mem_ctx, struct auth_serversupplied_info *server_info, uint32_t info2_mask, diff --git a/source3/rpc_server/srv_spoolss_util.h b/source3/rpc_server/srv_spoolss_util.h index ede313fc3f..1590db2c64 100644 --- a/source3/rpc_server/srv_spoolss_util.h +++ b/source3/rpc_server/srv_spoolss_util.h @@ -71,6 +71,10 @@ enum spoolss_PrinterInfo2Mask { SPOOLSS_PRINTER_INFO_STATUS | \ SPOOLSS_PRINTER_INFO_UNTILTIME +WERROR winreg_create_printer(TALLOC_CTX *mem_ctx, + struct auth_serversupplied_info *server_info, + const char *sharename); + /** * @internal * |