static NTSTATUS open_internal_samr_pipe(TALLOC_CTX *mem_ctx, struct rpc_pipe_client **samr_pipe) { struct rpc_pipe_client *cli = NULL; struct auth_serversupplied_info *session_info = NULL; NTSTATUS status; if (session_info == NULL) { status = make_session_info_system(mem_ctx, &session_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("open_samr_pipe: Could not create auth_serversupplied_info: %s\n", nt_errstr(status))); return status; } } /* create a samr connection */ status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr.syntax_id, session_info, NULL, winbind_messaging_context(), &cli); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("open_samr_pipe: Could not connect to samr_pipe: %s\n", nt_errstr(status))); return status; } if (samr_pipe) { *samr_pipe = cli; } return NT_STATUS_OK; }
static void store_printer_guid(struct messaging_context *msg_ctx, const char *printer, struct GUID guid) { TALLOC_CTX *tmp_ctx; struct auth_serversupplied_info *session_info = NULL; const char *guid_str; DATA_BLOB blob; NTSTATUS status; WERROR result; tmp_ctx = talloc_new(NULL); if (!tmp_ctx) { DEBUG(0, ("store_printer_guid: Out of memory?!\n")); return; } status = make_session_info_system(tmp_ctx, &session_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("store_printer_guid: " "Could not create system session_info\n")); goto done; } guid_str = GUID_string(tmp_ctx, &guid); if (!guid_str) { DEBUG(0, ("store_printer_guid: Out of memory?!\n")); goto done; } /* We used to store this as a REG_BINARY but that causes Vista to whine */ if (!push_reg_sz(tmp_ctx, &blob, guid_str)) { DEBUG(0, ("store_printer_guid: " "Could not marshall string %s for objectGUID\n", guid_str)); goto done; } result = winreg_set_printer_dataex(tmp_ctx, session_info, msg_ctx, printer, SPOOL_DSSPOOLER_KEY, "objectGUID", REG_SZ, blob.data, blob.length); if (!W_ERROR_IS_OK(result)) { DEBUG(0, ("store_printer_guid: " "Failed to store GUID for printer %s\n", printer)); } done: talloc_free(tmp_ctx); }
bool nt_printing_tdb_migrate(struct messaging_context *msg_ctx) { const char *drivers_path; const char *printers_path; const char *forms_path; bool drivers_exists; bool printers_exists; bool forms_exists; struct auth_session_info *session_info; struct rpc_pipe_client *winreg_pipe = NULL; TALLOC_CTX *tmp_ctx = talloc_stackframe(); NTSTATUS status; /* paths talloced on new stackframe */ drivers_path = state_path("ntdrivers.tdb"); printers_path = state_path("ntprinters.tdb"); forms_path = state_path("ntforms.tdb"); if ((drivers_path == NULL) || (printers_path == NULL) || (forms_path == NULL)) { talloc_free(tmp_ctx); return false; } drivers_exists = file_exist(drivers_path); printers_exists = file_exist(printers_path); forms_exists = file_exist(forms_path); if (!drivers_exists && !printers_exists && !forms_exists) { talloc_free(tmp_ctx); return true; } status = make_session_info_system(tmp_ctx, &session_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Couldn't create session_info: %s\n", nt_errstr(status))); talloc_free(tmp_ctx); return false; } status = rpc_pipe_open_interface(tmp_ctx, &ndr_table_winreg, session_info, NULL, NULL, msg_ctx, &winreg_pipe); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Couldn't open internal winreg pipe: %s\n", nt_errstr(status))); talloc_free(tmp_ctx); return false; } if (drivers_exists) { status = migrate_internal(tmp_ctx, drivers_path, winreg_pipe); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Couldn't migrate drivers tdb file: %s\n", nt_errstr(status))); talloc_free(tmp_ctx); return false; } } if (printers_exists) { status = migrate_internal(tmp_ctx, printers_path, winreg_pipe); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Couldn't migrate printers tdb file: %s\n", nt_errstr(status))); talloc_free(tmp_ctx); return false; } } if (forms_exists) { status = migrate_internal(tmp_ctx, forms_path, winreg_pipe); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Couldn't migrate forms tdb file: %s\n", nt_errstr(status))); talloc_free(tmp_ctx); return false; } } talloc_free(tmp_ctx); return true; }
NTSTATUS auth3_generate_session_info(struct auth4_context *auth_context, TALLOC_CTX *mem_ctx, void *server_returned_info, const char *original_user_name, uint32_t session_info_flags, struct auth_session_info **session_info) { struct auth_user_info_dc *user_info = NULL; struct auth_serversupplied_info *server_info = NULL; NTSTATUS nt_status; /* * This is a hack, some callers... * * Some callers pass auth_user_info_dc, the SCHANNEL and * NCALRPC_AS_SYSTEM gensec modules. * * While the reset passes auth3_check_password() returned. */ user_info = talloc_get_type(server_returned_info, struct auth_user_info_dc); if (user_info != NULL) { const struct dom_sid *sid; int cmp; /* * This should only be called from SCHANNEL or NCALRPC_AS_SYSTEM */ if (user_info->num_sids != 1) { return NT_STATUS_INTERNAL_ERROR; } sid = &user_info->sids[PRIMARY_USER_SID_INDEX]; cmp = dom_sid_compare(sid, &global_sid_System); if (cmp == 0) { return make_session_info_system(mem_ctx, session_info); } cmp = dom_sid_compare(sid, &global_sid_Anonymous); if (cmp == 0) { /* * TODO: use auth_anonymous_session_info() here? */ return make_session_info_guest(mem_ctx, session_info); } return NT_STATUS_INTERNAL_ERROR; } server_info = talloc_get_type_abort(server_returned_info, struct auth_serversupplied_info); nt_status = create_local_token(mem_ctx, server_info, NULL, original_user_name, session_info); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(10, ("create_local_token failed: %s\n", nt_errstr(nt_status))); return nt_status; } return NT_STATUS_OK; }
/** * @brief Purge stale printers and reload from pre-populated pcap cache. * * This function should normally only be called as a callback on a successful * pcap_cache_reload(). * * This function can cause DELETION of printers and drivers from our registry, * so calling it on a failed pcap reload may REMOVE permanently all printers * and drivers. * * @param[in] ev The event context. * * @param[in] msg_ctx The messaging context. */ static void delete_and_reload_printers_full(struct tevent_context *ev, struct messaging_context *msg_ctx) { struct auth_session_info *session_info = NULL; struct spoolss_PrinterInfo2 *pinfo2 = NULL; int n_services; int pnum; int snum; const char *pname; const char *sname; NTSTATUS status; n_services = lp_numservices(); pnum = lp_servicenumber(PRINTERS_NAME); status = make_session_info_system(talloc_tos(), &session_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("reload_printers: " "Could not create system session_info\n")); /* can't remove stale printers before we * are fully initilized */ return; } /* * Add default config for printers added to smb.conf file and remove * stale printers */ for (snum = 0; snum < n_services; snum++) { /* avoid removing PRINTERS_NAME */ if (snum == pnum) { continue; } /* skip no-printer services */ if (!snum_is_shared_printer(snum)) { continue; } sname = lp_const_servicename(snum); pname = lp_printername(session_info, snum); /* check printer, but avoid removing non-autoloaded printers */ if (lp_autoloaded(snum) && !pcap_printername_ok(pname)) { DEBUG(3, ("removing stale printer %s\n", pname)); if (is_printer_published(session_info, session_info, msg_ctx, NULL, lp_servicename(session_info, snum), &pinfo2)) { nt_printer_publish(session_info, session_info, msg_ctx, pinfo2, DSPRINT_UNPUBLISH); TALLOC_FREE(pinfo2); } nt_printer_remove(session_info, session_info, msg_ctx, pname); } else { DEBUG(8, ("Adding default registry entry for printer " "[%s], if it doesn't exist.\n", sname)); nt_printer_add(session_info, session_info, msg_ctx, sname); } } /* finally, purge old snums */ delete_and_reload_printers(); TALLOC_FREE(session_info); }
WERROR check_published_printers(struct messaging_context *msg_ctx) { ADS_STATUS ads_rc; ADS_STRUCT *ads = NULL; int snum; int n_services = lp_numservices(); TALLOC_CTX *tmp_ctx = NULL; struct auth_serversupplied_info *session_info = NULL; struct spoolss_PrinterInfo2 *pinfo2; NTSTATUS status; WERROR result; tmp_ctx = talloc_new(NULL); if (!tmp_ctx) return WERR_NOMEM; ads = ads_init(lp_realm(), lp_workgroup(), NULL); if (!ads) { DEBUG(3, ("ads_init() failed\n")); return WERR_SERVER_UNAVAILABLE; } setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1); SAFE_FREE(ads->auth.password); ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); /* ads_connect() will find the DC for us */ ads_rc = ads_connect(ads); if (!ADS_ERR_OK(ads_rc)) { DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc))); result = WERR_ACCESS_DENIED; goto done; } status = make_session_info_system(tmp_ctx, &session_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("check_published_printers: " "Could not create system session_info\n")); result = WERR_ACCESS_DENIED; goto done; } for (snum = 0; snum < n_services; snum++) { if (!lp_snum_ok(snum) || !lp_print_ok(snum)) { continue; } result = winreg_get_printer(tmp_ctx, session_info, msg_ctx, lp_servicename(snum), &pinfo2); if (!W_ERROR_IS_OK(result)) { continue; } if (pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) { nt_printer_publish_ads(msg_ctx, ads, pinfo2); } TALLOC_FREE(pinfo2); } result = WERR_OK; done: ads_destroy(&ads); ads_kdestroy("MEMORY:prtpub_cache"); talloc_free(tmp_ctx); return result; }
static bool api_pipe_bind_req(struct pipes_struct *p, struct ncacn_packet *pkt) { struct dcerpc_auth auth_info; uint16 assoc_gid; unsigned int auth_type = DCERPC_AUTH_TYPE_NONE; NTSTATUS status; struct ndr_syntax_id id; uint8_t pfc_flags = 0; union dcerpc_payload u; struct dcerpc_ack_ctx bind_ack_ctx; DATA_BLOB auth_resp = data_blob_null; DATA_BLOB auth_blob = data_blob_null; const struct ndr_interface_table *table; /* No rebinds on a bound pipe - use alter context. */ if (p->pipe_bound) { DEBUG(2,("Rejecting bind request on bound rpc connection\n")); return setup_bind_nak(p, pkt); } if (pkt->u.bind.num_contexts == 0) { DEBUG(0, ("api_pipe_bind_req: no rpc contexts around\n")); goto err_exit; } /* * Try and find the correct pipe name to ensure * that this is a pipe name we support. */ id = pkt->u.bind.ctx_list[0].abstract_syntax; table = ndr_table_by_uuid(&id.uuid); if (table == NULL) { DEBUG(0,("unknown interface\n")); return false; } if (rpc_srv_pipe_exists_by_id(&id)) { DEBUG(3, ("api_pipe_bind_req: %s -> %s rpc service\n", rpc_srv_get_pipe_cli_name(&id), rpc_srv_get_pipe_srv_name(&id))); } else { status = smb_probe_module( "rpc", dcerpc_default_transport_endpoint(pkt, NCACN_NP, table)); if (NT_STATUS_IS_ERR(status)) { DEBUG(3,("api_pipe_bind_req: Unknown rpc service name " "%s in bind request.\n", ndr_interface_name(&id.uuid, id.if_version))); return setup_bind_nak(p, pkt); } if (rpc_srv_get_pipe_interface_by_cli_name( dcerpc_default_transport_endpoint(pkt, NCACN_NP, table), &id)) { DEBUG(3, ("api_pipe_bind_req: %s -> %s rpc service\n", rpc_srv_get_pipe_cli_name(&id), rpc_srv_get_pipe_srv_name(&id))); } else { DEBUG(0, ("module %s doesn't provide functions for " "pipe %s!\n", ndr_interface_name(&id.uuid, id.if_version), ndr_interface_name(&id.uuid, id.if_version))); return setup_bind_nak(p, pkt); } } DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__)); if (pkt->u.bind.assoc_group_id != 0) { assoc_gid = pkt->u.bind.assoc_group_id; } else { assoc_gid = 0x53f0; } /* * Create the bind response struct. */ /* If the requested abstract synt uuid doesn't match our client pipe, reject the bind_ack & set the transfer interface synt to all 0's, ver 0 (observed when NT5 attempts to bind to abstract interfaces unknown to NT4) Needed when adding entries to a DACL from NT5 - SK */ if (check_bind_req(p, &pkt->u.bind.ctx_list[0].abstract_syntax, &pkt->u.bind.ctx_list[0].transfer_syntaxes[0], pkt->u.bind.ctx_list[0].context_id)) { bind_ack_ctx.result = 0; bind_ack_ctx.reason.value = 0; bind_ack_ctx.syntax = pkt->u.bind.ctx_list[0].transfer_syntaxes[0]; } else { p->pipe_bound = False; /* Rejection reason: abstract syntax not supported */ bind_ack_ctx.result = DCERPC_BIND_PROVIDER_REJECT; bind_ack_ctx.reason.value = DCERPC_BIND_REASON_ASYNTAX; bind_ack_ctx.syntax = ndr_syntax_id_null; } /* * Check if this is an authenticated bind request. */ if (pkt->auth_length) { /* Quick length check. Won't catch a bad auth footer, * prevents overrun. */ if (pkt->frag_length < RPC_HEADER_LEN + DCERPC_AUTH_TRAILER_LENGTH + pkt->auth_length) { DEBUG(0,("api_pipe_bind_req: auth_len (%u) " "too long for fragment %u.\n", (unsigned int)pkt->auth_length, (unsigned int)pkt->frag_length)); goto err_exit; } /* * Decode the authentication verifier. */ status = dcerpc_pull_dcerpc_auth(pkt, &pkt->u.bind.auth_info, &auth_info, p->endian); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n")); goto err_exit; } auth_type = auth_info.auth_type; /* Work out if we have to sign or seal etc. */ switch (auth_info.auth_level) { case DCERPC_AUTH_LEVEL_INTEGRITY: p->auth.auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; break; case DCERPC_AUTH_LEVEL_PRIVACY: p->auth.auth_level = DCERPC_AUTH_LEVEL_PRIVACY; break; case DCERPC_AUTH_LEVEL_CONNECT: p->auth.auth_level = DCERPC_AUTH_LEVEL_CONNECT; break; default: DEBUG(0, ("Unexpected auth level (%u).\n", (unsigned int)auth_info.auth_level )); goto err_exit; } switch (auth_type) { case DCERPC_AUTH_TYPE_NTLMSSP: if (!pipe_auth_generic_bind(p, pkt, &auth_info, &auth_resp)) { goto err_exit; } assoc_gid = 0x7a77; break; case DCERPC_AUTH_TYPE_SCHANNEL: if (!pipe_auth_generic_bind(p, pkt, &auth_info, &auth_resp)) { goto err_exit; } if (!session_info_set_session_key(p->session_info, generic_session_key())) { DEBUG(0, ("session_info_set_session_key failed\n")); goto err_exit; } p->pipe_bound = true; break; case DCERPC_AUTH_TYPE_SPNEGO: case DCERPC_AUTH_TYPE_KRB5: if (!pipe_auth_generic_bind(p, pkt, &auth_info, &auth_resp)) { goto err_exit; } break; case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM: if (p->transport == NCALRPC && p->ncalrpc_as_system) { TALLOC_FREE(p->session_info); status = make_session_info_system(p, &p->session_info); if (!NT_STATUS_IS_OK(status)) { goto err_exit; } auth_resp = data_blob_talloc(pkt, "NCALRPC_AUTH_OK", 15); p->auth.auth_type = DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM; p->pipe_bound = true; } else { goto err_exit; } break; case DCERPC_AUTH_TYPE_NONE: break; default: DEBUG(0, ("Unknown auth type %x requested.\n", auth_type)); goto err_exit; } } if (auth_type == DCERPC_AUTH_TYPE_NONE) { /* Unauthenticated bind request. */ /* We're finished - no more packets. */ p->auth.auth_type = DCERPC_AUTH_TYPE_NONE; /* We must set the pipe auth_level here also. */ p->auth.auth_level = DCERPC_AUTH_LEVEL_NONE; p->pipe_bound = True; /* The session key was initialized from the SMB * session in make_internal_rpc_pipe_p */ } ZERO_STRUCT(u.bind_ack); u.bind_ack.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN; u.bind_ack.max_recv_frag = RPC_MAX_PDU_FRAG_LEN; u.bind_ack.assoc_group_id = assoc_gid; /* name has to be \PIPE\xxxxx */ u.bind_ack.secondary_address = talloc_asprintf(pkt, "\\PIPE\\%s", rpc_srv_get_pipe_srv_name(&id)); if (!u.bind_ack.secondary_address) { DEBUG(0, ("Out of memory!\n")); goto err_exit; } u.bind_ack.secondary_address_size = strlen(u.bind_ack.secondary_address) + 1; u.bind_ack.num_results = 1; u.bind_ack.ctx_list = &bind_ack_ctx; /* NOTE: We leave the auth_info empty so we can calculate the padding * later and then append the auth_info --simo */ /* * Marshall directly into the outgoing PDU space. We * must do this as we need to set to the bind response * header and are never sending more than one PDU here. */ pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; if (p->auth.hdr_signing) { pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; } status = dcerpc_push_ncacn_packet(p->mem_ctx, DCERPC_PKT_BIND_ACK, pfc_flags, auth_resp.length, pkt->call_id, &u, &p->out_data.frag); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to marshall bind_ack packet. (%s)\n", nt_errstr(status))); } if (auth_resp.length) { status = dcerpc_push_dcerpc_auth(pkt, auth_type, auth_info.auth_level, 0, 1, /* auth_context_id */ &auth_resp, &auth_blob); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Marshalling of dcerpc_auth failed.\n")); goto err_exit; } } /* Now that we have the auth len store it into the right place in * the dcerpc header */ dcerpc_set_frag_length(&p->out_data.frag, p->out_data.frag.length + auth_blob.length); if (auth_blob.length) { if (!data_blob_append(p->mem_ctx, &p->out_data.frag, auth_blob.data, auth_blob.length)) { DEBUG(0, ("Append of auth info failed.\n")); goto err_exit; } } /* * Setup the lengths for the initial reply. */ p->out_data.data_sent_length = 0; p->out_data.current_pdu_sent = 0; TALLOC_FREE(auth_blob.data); return True; err_exit: data_blob_free(&p->out_data.frag); TALLOC_FREE(auth_blob.data); return setup_bind_nak(p, pkt); }