/* map a REG_DWORD to an ldap mod */ static bool map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods, const REGISTRY_VALUE *value) { char *str_value = NULL; ADS_STATUS status; if (value->type != REG_DWORD) return False; str_value = talloc_asprintf(ctx, "%d", *((uint32 *) value->data_p)); if (!str_value) { return False; } status = ads_mod_str(ctx, mods, value->valuename, str_value); return ADS_ERR_OK(status); }
ADS_STATUS ads_add_group_acct(ADS_STRUCT *ads, const char *group, const char *container, const char *comment) { TALLOC_CTX *ctx; ADS_MODLIST mods; ADS_STATUS status; char *new_dn; char *name_escaped = NULL; const char *objectClass[] = {"top", "group", NULL}; if (!(ctx = talloc_init("ads_add_group_acct"))) return ADS_ERROR(LDAP_NO_MEMORY); status = ADS_ERROR(LDAP_NO_MEMORY); if (!(name_escaped = escape_rdn_val_string_alloc(group))) goto done; if (!(new_dn = talloc_asprintf(ctx, "cn=%s,%s,%s", name_escaped, container, ads->config.bind_path))) goto done; if (!(mods = ads_init_mods(ctx))) goto done; ads_mod_str(ctx, &mods, "cn", group); ads_mod_strlist(ctx, &mods, "objectClass",objectClass); ads_mod_str(ctx, &mods, "name", group); if (comment && *comment) ads_mod_str(ctx, &mods, "description", comment); ads_mod_str(ctx, &mods, "sAMAccountName", group); status = ads_gen_add(ads, new_dn, mods); done: SAFE_FREE(name_escaped); talloc_destroy(ctx); return status; }
/* map a boolean REG_BINARY to an ldap mod */ static bool map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods, const REGISTRY_VALUE *value) { char *str_value; ADS_STATUS status; if ((value->type != REG_BINARY) || (value->size != 1)) return False; str_value = talloc_asprintf(ctx, "%s", *(value->data_p) ? "TRUE" : "FALSE"); if (!str_value) { return False; } status = ads_mod_str(ctx, mods, value->valuename, str_value); return ADS_ERR_OK(status); }
/* map a REG_SZ to an ldap mod */ static bool map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods, const REGISTRY_VALUE *value) { char *str_value = NULL; ADS_STATUS status; if (value->type != REG_SZ) return False; if (value->size && *((smb_ucs2_t *) value->data_p)) { pull_ucs2_talloc(ctx, &str_value, (const smb_ucs2_t *) value->data_p); status = ads_mod_str(ctx, mods, value->valuename, str_value); return ADS_ERR_OK(status); } return True; }
/* map a boolean REG_BINARY to an ldap mod */ static bool map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods, const char *name, struct registry_value *value) { const char *str_value; ADS_STATUS status; if (value->type != REG_BINARY) { return false; } if (value->data.length != 1) { return false; } str_value = *value->data.data ? "TRUE" : "FALSE"; status = ads_mod_str(ctx, mods, name, str_value); return ADS_ERR_OK(status); }
/* map a REG_SZ to an ldap mod */ static bool map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods, const char *name, struct registry_value *value) { const char *str_value = NULL; ADS_STATUS status; if (value->type != REG_SZ) return false; if (value->data.length && value->data.data) { if (!pull_reg_sz(ctx, &value->data, &str_value)) { return false; } status = ads_mod_str(ctx, mods, name, str_value); return ADS_ERR_OK(status); } return true; }
/* map a REG_DWORD to an ldap mod */ static bool map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods, const char *name, struct registry_value *value) { char *str_value = NULL; ADS_STATUS status; if (value->type != REG_DWORD) { return false; } if (value->data.length != sizeof(uint32)) { return false; } str_value = talloc_asprintf(ctx, "%d", IVAL(value->data.data, 0)); if (!str_value) { return false; } status = ads_mod_str(ctx, mods, name, str_value); return ADS_ERR_OK(status); }
ADS_STATUS ads_add_user_acct(ADS_STRUCT *ads, const char *user, const char *container, const char *fullname) { TALLOC_CTX *ctx; ADS_MODLIST mods; ADS_STATUS status; const char *upn, *new_dn, *name, *controlstr; char *name_escaped = NULL; const char *objectClass[] = {"top", "person", "organizationalPerson", "user", NULL}; if (fullname && *fullname) name = fullname; else name = user; if (!(ctx = talloc_init("ads_add_user_acct"))) return ADS_ERROR(LDAP_NO_MEMORY); status = ADS_ERROR(LDAP_NO_MEMORY); if (!(upn = talloc_asprintf(ctx, "%s@%s", user, ads->config.realm))) goto done; if (!(name_escaped = escape_rdn_val_string_alloc(name))) goto done; if (!(new_dn = talloc_asprintf(ctx, "cn=%s,%s,%s", name_escaped, container, ads->config.bind_path))) goto done; if (!(controlstr = talloc_asprintf(ctx, "%u", (UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE)))) goto done; if (!(mods = ads_init_mods(ctx))) goto done; ads_mod_str(ctx, &mods, "cn", name); ads_mod_strlist(ctx, &mods, "objectClass", objectClass); ads_mod_str(ctx, &mods, "userPrincipalName", upn); ads_mod_str(ctx, &mods, "name", name); ads_mod_str(ctx, &mods, "displayName", name); ads_mod_str(ctx, &mods, "sAMAccountName", user); ads_mod_str(ctx, &mods, "userAccountControl", controlstr); status = ads_gen_add(ads, new_dn, mods); done: SAFE_FREE(name_escaped); talloc_destroy(ctx); return status; }
static WERROR nt_printer_publish_ads(struct messaging_context *msg_ctx, ADS_STRUCT *ads, struct spoolss_PrinterInfo2 *pinfo2) { ADS_STATUS ads_rc; LDAPMessage *res; char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped; char *srv_dn_utf8, **srv_cn_utf8; TALLOC_CTX *ctx; ADS_MODLIST mods; const char *attrs[] = {"objectGUID", NULL}; struct GUID guid; WERROR win_rc = WERR_OK; size_t converted_size; const char *printer = pinfo2->sharename; /* build the ads mods */ ctx = talloc_init("nt_printer_publish_ads"); if (ctx == NULL) { return WERR_NOMEM; } DEBUG(5, ("publishing printer %s\n", printer)); /* figure out where to publish */ ads_find_machine_acct(ads, &res, lp_netbios_name()); /* We use ldap_get_dn here as we need the answer * in utf8 to call ldap_explode_dn(). JRA. */ srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res); if (!srv_dn_utf8) { TALLOC_FREE(ctx); return WERR_SERVER_UNAVAILABLE; } ads_msgfree(ads, res); srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1); if (!srv_cn_utf8) { TALLOC_FREE(ctx); ldap_memfree(srv_dn_utf8); return WERR_SERVER_UNAVAILABLE; } /* Now convert to CH_UNIX. */ if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) { TALLOC_FREE(ctx); ldap_memfree(srv_dn_utf8); ldap_memfree(srv_cn_utf8); return WERR_SERVER_UNAVAILABLE; } if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) { TALLOC_FREE(ctx); ldap_memfree(srv_dn_utf8); ldap_memfree(srv_cn_utf8); TALLOC_FREE(srv_dn); return WERR_SERVER_UNAVAILABLE; } ldap_memfree(srv_dn_utf8); ldap_memfree(srv_cn_utf8); srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0); if (!srv_cn_escaped) { TALLOC_FREE(ctx); return WERR_SERVER_UNAVAILABLE; } sharename_escaped = escape_rdn_val_string_alloc(printer); if (!sharename_escaped) { SAFE_FREE(srv_cn_escaped); TALLOC_FREE(ctx); return WERR_SERVER_UNAVAILABLE; } prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn); SAFE_FREE(srv_cn_escaped); SAFE_FREE(sharename_escaped); mods = ads_init_mods(ctx); if (mods == NULL) { SAFE_FREE(prt_dn); TALLOC_FREE(ctx); return WERR_NOMEM; } ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, printer); /* publish it */ ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods); if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) { int i; for (i=0; mods[i] != 0; i++) ; mods[i] = (LDAPMod *)-1; ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods); } if (!ADS_ERR_OK(ads_rc)) { DEBUG(3, ("error publishing %s: %s\n", printer, ads_errstr(ads_rc))); } /* retreive the guid and store it locally */ if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) { bool guid_ok; ZERO_STRUCT(guid); guid_ok = ads_pull_guid(ads, res, &guid); ads_msgfree(ads, res); if (guid_ok) { store_printer_guid(msg_ctx, printer, guid); } } TALLOC_FREE(ctx); return win_rc; }
static WERROR nt_printer_info_to_mods(TALLOC_CTX *ctx, struct spoolss_PrinterInfo2 *info2, ADS_MODLIST *mods) { char *info_str; ads_mod_str(ctx, mods, SPOOL_REG_PRINTERNAME, info2->sharename); ads_mod_str(ctx, mods, SPOOL_REG_SHORTSERVERNAME, global_myname()); ads_mod_str(ctx, mods, SPOOL_REG_SERVERNAME, get_mydnsfullname()); info_str = talloc_asprintf(ctx, "\\\\%s\\%s", get_mydnsfullname(), info2->sharename); if (info_str == NULL) { return WERR_NOMEM; } ads_mod_str(ctx, mods, SPOOL_REG_UNCNAME, info_str); info_str = talloc_asprintf(ctx, "%d", 4); if (info_str == NULL) { return WERR_NOMEM; } ads_mod_str(ctx, mods, SPOOL_REG_VERSIONNUMBER, info_str); /* empty strings in the mods list result in an attrubute error */ if (strlen(info2->drivername) != 0) ads_mod_str(ctx, mods, SPOOL_REG_DRIVERNAME, info2->drivername); if (strlen(info2->location) != 0) ads_mod_str(ctx, mods, SPOOL_REG_LOCATION, info2->location); if (strlen(info2->comment) != 0) ads_mod_str(ctx, mods, SPOOL_REG_DESCRIPTION, info2->comment); if (strlen(info2->portname) != 0) ads_mod_str(ctx, mods, SPOOL_REG_PORTNAME, info2->portname); if (strlen(info2->sepfile) != 0) ads_mod_str(ctx, mods, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile); info_str = talloc_asprintf(ctx, "%u", info2->starttime); if (info_str == NULL) { return WERR_NOMEM; } ads_mod_str(ctx, mods, SPOOL_REG_PRINTSTARTTIME, info_str); info_str = talloc_asprintf(ctx, "%u", info2->untiltime); if (info_str == NULL) { return WERR_NOMEM; } ads_mod_str(ctx, mods, SPOOL_REG_PRINTENDTIME, info_str); info_str = talloc_asprintf(ctx, "%u", info2->priority); if (info_str == NULL) { return WERR_NOMEM; } ads_mod_str(ctx, mods, SPOOL_REG_PRIORITY, info_str); if (info2->attributes & PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS) { ads_mod_str(ctx, mods, SPOOL_REG_PRINTKEEPPRINTEDJOBS, "TRUE"); } else { ads_mod_str(ctx, mods, SPOOL_REG_PRINTKEEPPRINTEDJOBS, "FALSE"); } switch (info2->attributes & 0x3) { case 0: ads_mod_str(ctx, mods, SPOOL_REG_PRINTSPOOLING, SPOOL_REGVAL_PRINTWHILESPOOLING); break; case 1: ads_mod_str(ctx, mods, SPOOL_REG_PRINTSPOOLING, SPOOL_REGVAL_PRINTAFTERSPOOLED); break; case 2: ads_mod_str(ctx, mods, SPOOL_REG_PRINTSPOOLING, SPOOL_REGVAL_PRINTDIRECT); break; default: DEBUG(3, ("unsupported printer attributes %x\n", info2->attributes)); } return WERR_OK; }
WERROR get_remote_printer_publishing_data(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, ADS_MODLIST *mods, const char *printer) { struct dcerpc_binding_handle *b = cli->binding_handle; WERROR result; char *printername; struct spoolss_PrinterEnumValues *info; uint32_t count; uint32 i; struct policy_handle pol; WERROR werr; if ((asprintf(&printername, "%s\\%s", cli->srv_name_slash, printer) == -1)) { DEBUG(3, ("Insufficient memory\n")); return WERR_NOMEM; } result = rpccli_spoolss_openprinter_ex(cli, mem_ctx, printername, SEC_FLAG_MAXIMUM_ALLOWED, &pol); if (!W_ERROR_IS_OK(result)) { DEBUG(3, ("Unable to open printer %s, error is %s.\n", printername, win_errstr(result))); SAFE_FREE(printername); return result; } result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol, SPOOL_DSDRIVER_KEY, 0, &count, &info); if (!W_ERROR_IS_OK(result)) { DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n", printername, win_errstr(result))); } else { /* Have the data we need now, so start building */ for (i=0; i < count; i++) { struct registry_value v; v.type = info[i].type; v.data = *info[i].data; map_regval_to_ads(mem_ctx, mods, info[i].value_name, &v); } } result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol, SPOOL_DSSPOOLER_KEY, 0, &count, &info); if (!W_ERROR_IS_OK(result)) { DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n", printername, win_errstr(result))); } else { for (i=0; i < count; i++) { struct registry_value v; v.type = info[i].type; v.data = *info[i].data; map_regval_to_ads(mem_ctx, mods, info[i].value_name, &v); } } ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer); dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &werr); SAFE_FREE(printername); return result; }
/* add a printer to the directory */ ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn, TALLOC_CTX *ctx, ADS_MODLIST *mods) { ads_mod_str(ctx, mods, "objectClass", "printQueue"); return ads_gen_add(ads, prt_dn, *mods); }
WERROR get_remote_printer_publishing_data(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, ADS_MODLIST *mods, const char *printer) { WERROR result; char *printername, *servername; REGVAL_CTR *dsdriver_ctr, *dsspooler_ctr; uint32 i; POLICY_HND pol; asprintf(&servername, "\\\\%s", cli->cli->desthost); asprintf(&printername, "%s\\%s", servername, printer); if (!servername || !printername) { DEBUG(3, ("Insufficient memory\n")); return WERR_NOMEM; } result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, servername, cli->cli->user_name, &pol); if (!W_ERROR_IS_OK(result)) { DEBUG(3, ("Unable to open printer %s, error is %s.\n", printername, dos_errstr(result))); SAFE_FREE(printername); return result; } if ( !(dsdriver_ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) ) { SAFE_FREE(printername); return WERR_NOMEM; } result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol, SPOOL_DSDRIVER_KEY, dsdriver_ctr); if (!W_ERROR_IS_OK(result)) { DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n", printername, dos_errstr(result))); } else { uint32 num_values = regval_ctr_numvals( dsdriver_ctr ); /* Have the data we need now, so start building */ for (i=0; i < num_values; i++) { map_regval_to_ads(mem_ctx, mods, dsdriver_ctr->values[i]); } } if ( !(dsspooler_ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) ) { SAFE_FREE(printername); return WERR_NOMEM; } result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol, SPOOL_DSSPOOLER_KEY, dsspooler_ctr); if (!W_ERROR_IS_OK(result)) { DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n", printername, dos_errstr(result))); } else { uint32 num_values = regval_ctr_numvals( dsspooler_ctr ); for (i=0; i<num_values; i++) { map_regval_to_ads(mem_ctx, mods, dsspooler_ctr->values[i]); } } ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer); TALLOC_FREE( dsdriver_ctr ); TALLOC_FREE( dsspooler_ctr ); rpccli_spoolss_close_printer(cli, mem_ctx, &pol); SAFE_FREE(printername); return result; }