/* reply to a GETDC request */ static void nbtd_netlogon_getdc(struct dgram_mailslot_handler *dgmslot, struct nbtd_interface *iface, struct nbt_dgram_packet *packet, const struct socket_address *src, struct nbt_netlogon_packet *netlogon) { struct nbt_name *name = &packet->data.msg.dest_name; struct nbtd_interface *reply_iface = nbtd_find_reply_iface(iface, src->addr, false); struct nbt_netlogon_response_from_pdc *pdc; struct ldb_context *samctx; struct nbt_netlogon_response netlogon_response; /* only answer getdc requests on the PDC or LOGON names */ if (name->type != NBT_NAME_PDC && name->type != NBT_NAME_LOGON) { return; } samctx = iface->nbtsrv->sam_ctx; if (lpcfg_server_role(iface->nbtsrv->task->lp_ctx) != ROLE_DOMAIN_CONTROLLER || !samdb_is_pdc(samctx)) { DEBUG(2, ("Not a PDC, so not processing LOGON_PRIMARY_QUERY\n")); return; } if (strcasecmp_m(name->name, lpcfg_workgroup(iface->nbtsrv->task->lp_ctx)) != 0) { DEBUG(5,("GetDC requested for a domian %s that we don't host\n", name->name)); return; } /* setup a GETDC reply */ ZERO_STRUCT(netlogon_response); netlogon_response.response_type = NETLOGON_GET_PDC; pdc = &netlogon_response.data.get_pdc; pdc->command = NETLOGON_RESPONSE_FROM_PDC; pdc->pdc_name = lpcfg_netbios_name(iface->nbtsrv->task->lp_ctx); pdc->unicode_pdc_name = pdc->pdc_name; pdc->domain_name = lpcfg_workgroup(iface->nbtsrv->task->lp_ctx); pdc->nt_version = 1; pdc->lmnt_token = 0xFFFF; pdc->lm20_token = 0xFFFF; dgram_mailslot_netlogon_reply(reply_iface->dgmsock, packet, lpcfg_netbios_name(iface->nbtsrv->task->lp_ctx), netlogon->req.pdc.mailslot_name, &netlogon_response); }
/** * Return a anonymous logon for anonymous users (username = "") * * Typically used as the first module in the auth chain, this allows * anonymou logons to be dealt with in one place. Non-anonymou logons 'fail' * and pass onto the next module. **/ static NTSTATUS anonymous_check_password(struct auth_method_context *ctx, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, struct auth_user_info_dc **_user_info_dc) { return auth_anonymous_user_info_dc(mem_ctx, lpcfg_netbios_name(ctx->auth_ctx->lp_ctx), _user_info_dc); }
/* handle incoming netlogon mailslot requests */ void nbtd_mailslot_netlogon_handler(struct dgram_mailslot_handler *dgmslot, struct nbt_dgram_packet *packet, struct socket_address *src) { NTSTATUS status = NT_STATUS_NO_MEMORY; struct nbtd_interface *iface = talloc_get_type(dgmslot->private_data, struct nbtd_interface); struct nbtd_interface *reply_iface = nbtd_find_reply_iface( iface, src->addr, false); struct nbt_netlogon_response *response = NULL; char *reply_mailslot = NULL; if (reply_iface->ip_address == NULL) { DBG_WARNING("Could not obtain own IP address for datagram " "socket\n"); return; } status = nbtd_mailslot_netlogon_reply( iface, packet, src, dgmslot, &response, &reply_mailslot); if (NT_STATUS_IS_OK(status)) { dgram_mailslot_netlogon_reply( reply_iface->dgmsock, packet, lpcfg_netbios_name(iface->nbtsrv->task->lp_ctx), reply_mailslot, response); } TALLOC_FREE(response); TALLOC_FREE(reply_mailslot); }
/* ioctl - used for job query */ static NTSTATUS print_ioctl(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, union smb_ioctl *io) { char *p; if (io->generic.level != RAW_IOCTL_IOCTL) { return NT_STATUS_NOT_IMPLEMENTED; } if (io->ioctl.in.request == IOCTL_QUERY_JOB_INFO) { /* a request for the print job id of an open print job */ io->ioctl.out.blob = data_blob_talloc(req, NULL, 32); data_blob_clear(&io->ioctl.out.blob); p = (char *)io->ioctl.out.blob.data; SSVAL(p,0, 1 /* REWRITE: fsp->rap_print_jobid */); push_string(p+2, lpcfg_netbios_name(ntvfs->ctx->lp_ctx), 15, STR_TERMINATE|STR_ASCII); push_string(p+18, ntvfs->ctx->config->name, 13, STR_TERMINATE|STR_ASCII); return NT_STATUS_OK; } return NT_STATUS_INVALID_PARAMETER; }
NTSTATUS auth_system_session_info(TALLOC_CTX *parent_ctx, struct loadparm_context *lp_ctx, struct auth_session_info **_session_info) { NTSTATUS nt_status; struct auth_user_info_dc *user_info_dc = NULL; struct auth_session_info *session_info = NULL; TALLOC_CTX *mem_ctx = talloc_new(parent_ctx); nt_status = auth_system_user_info_dc(mem_ctx, lpcfg_netbios_name(lp_ctx), &user_info_dc); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); return nt_status; } /* references the user_info_dc into the session_info */ nt_status = auth_generate_session_info(parent_ctx, NULL, NULL, user_info_dc, AUTH_SESSION_INFO_SIMPLE_PRIVILEGES, &session_info); talloc_free(mem_ctx); NT_STATUS_NOT_OK_RETURN(nt_status); session_info->credentials = cli_credentials_init(session_info); if (!session_info->credentials) { return NT_STATUS_NO_MEMORY; } cli_credentials_set_conf(session_info->credentials, lp_ctx); cli_credentials_set_machine_account_pending(session_info->credentials, lp_ctx); *_session_info = session_info; return NT_STATUS_OK; }
/* setup our listening sockets on the configured network interfaces */ NTSTATUS nbtd_startup_interfaces(struct nbtd_server *nbtsrv, struct loadparm_context *lp_ctx, struct interface *ifaces) { int num_interfaces = iface_count(ifaces); int i; TALLOC_CTX *tmp_ctx = talloc_new(nbtsrv); NTSTATUS status; /* if we are allowing incoming packets from any address, then we also need to bind to the wildcard address */ if (!lpcfg_bind_interfaces_only(lp_ctx)) { const char *primary_address; /* the primary address is the address we will return for non-WINS queries not made on a specific interface */ if (num_interfaces > 0) { primary_address = iface_n_ip(ifaces, 0); } else { primary_address = inet_ntoa(interpret_addr2( lpcfg_netbios_name(lp_ctx))); } primary_address = talloc_strdup(tmp_ctx, primary_address); NT_STATUS_HAVE_NO_MEMORY(primary_address); status = nbtd_add_socket(nbtsrv, lp_ctx, "0.0.0.0", primary_address, talloc_strdup(tmp_ctx, "255.255.255.255"), talloc_strdup(tmp_ctx, "0.0.0.0")); NT_STATUS_NOT_OK_RETURN(status); } for (i=0; i<num_interfaces; i++) { const char *bcast = iface_n_bcast(ifaces, i); const char *address, *netmask; /* we can't assume every interface is broadcast capable */ if (bcast == NULL) continue; address = talloc_strdup(tmp_ctx, iface_n_ip(ifaces, i)); bcast = talloc_strdup(tmp_ctx, bcast); netmask = talloc_strdup(tmp_ctx, iface_n_netmask(ifaces, i)); status = nbtd_add_socket(nbtsrv, lp_ctx, address, address, bcast, netmask); NT_STATUS_NOT_OK_RETURN(status); } if (lpcfg_wins_server_list(lp_ctx)) { status = nbtd_add_wins_socket(nbtsrv); NT_STATUS_NOT_OK_RETURN(status); } talloc_free(tmp_ctx); return NT_STATUS_OK; }
/* spoolss_RemoteFindFirstPrinterChangeNotifyEx */ static WERROR dcesrv_spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r) { struct dcerpc_pipe *p; struct dcerpc_binding *binding; NTSTATUS status; struct spoolss_ReplyOpenPrinter rop; struct cli_credentials *creds; struct policy_handle notify_handle; DEBUG(2, ("Received RFFPCNex from %s\n", r->in.local_machine)); /* * TODO: for now just open a connection to the client and drop it again * to keep the w2k3 PrintServer * happy to allow to open the Add Printer GUI * and the torture suite passing */ binding = talloc_zero(mem_ctx, struct dcerpc_binding); binding->transport = NCACN_NP; if (strncmp(r->in.local_machine, "\\\\", 2)) return WERR_INVALID_COMPUTERNAME; binding->host = r->in.local_machine+2; creds = cli_credentials_init_anon(mem_ctx); /* FIXME: Use machine credentials instead ? */ status = dcerpc_pipe_connect_b(mem_ctx, &p, binding, &ndr_table_spoolss, creds, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx); if (NT_STATUS_IS_ERR(status)) { DEBUG(0, ("unable to call back to %s\n", r->in.local_machine)); return WERR_SERVER_UNAVAILABLE; } ZERO_STRUCT(rop); rop.in.server_name = lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx); W_ERROR_HAVE_NO_MEMORY(rop.in.server_name); rop.in.printer_local = 0; rop.in.type = REG_NONE; rop.in.bufsize = 0; rop.in.buffer = NULL; rop.out.handle = ¬ify_handle; status = dcerpc_spoolss_ReplyOpenPrinter_r(p->binding_handle, mem_ctx, &rop); if (NT_STATUS_IS_ERR(status)) { DEBUG(0, ("unable to open remote printer %s\n", r->in.local_machine)); return WERR_SERVER_UNAVAILABLE; } talloc_free(p); return WERR_OK; }
const char *lpcfg_sam_name(struct loadparm_context *lp_ctx) { switch (lpcfg_server_role(lp_ctx)) { case ROLE_DOMAIN_BDC: case ROLE_DOMAIN_PDC: return lpcfg_workgroup(lp_ctx); default: return lpcfg_netbios_name(lp_ctx); } }
/** * Specifies default values for domain, workstation and realm * from the smb.conf configuration file * * @param cred Credentials structure to fill in */ _PUBLIC_ void cli_credentials_set_conf(struct cli_credentials *cred, struct loadparm_context *lp_ctx) { cli_credentials_set_username(cred, "", CRED_UNINITIALISED); if (lpcfg_parm_is_cmdline(lp_ctx, "workgroup")) { cli_credentials_set_domain(cred, lpcfg_workgroup(lp_ctx), CRED_SPECIFIED); } else { cli_credentials_set_domain(cred, lpcfg_workgroup(lp_ctx), CRED_UNINITIALISED); } if (lpcfg_parm_is_cmdline(lp_ctx, "netbios name")) { cli_credentials_set_workstation(cred, lpcfg_netbios_name(lp_ctx), CRED_SPECIFIED); } else { cli_credentials_set_workstation(cred, lpcfg_netbios_name(lp_ctx), CRED_UNINITIALISED); } if (lpcfg_parm_is_cmdline(lp_ctx, "realm")) { cli_credentials_set_realm(cred, lpcfg_realm(lp_ctx), CRED_SPECIFIED); } else { cli_credentials_set_realm(cred, lpcfg_realm(lp_ctx), CRED_UNINITIALISED); } }
/* reply to a ADS style GETDC request */ static void nbtd_netlogon_samlogon(struct dgram_mailslot_handler *dgmslot, struct nbtd_interface *iface, struct nbt_dgram_packet *packet, const struct socket_address *src, struct nbt_netlogon_packet *netlogon) { struct nbt_name *name = &packet->data.msg.dest_name; struct nbtd_interface *reply_iface = nbtd_find_reply_iface(iface, src->addr, false); struct ldb_context *samctx; const char *my_ip = reply_iface->ip_address; struct dom_sid *sid; struct nbt_netlogon_response netlogon_response; NTSTATUS status; if (!my_ip) { DEBUG(0, ("Could not obtain own IP address for datagram socket\n")); return; } /* only answer getdc requests on the PDC or LOGON names */ if (name->type != NBT_NAME_PDC && name->type != NBT_NAME_LOGON) { return; } samctx = iface->nbtsrv->sam_ctx; if (netlogon->req.logon.sid_size) { sid = &netlogon->req.logon.sid; } else { sid = NULL; } status = fill_netlogon_samlogon_response(samctx, packet, NULL, name->name, sid, NULL, netlogon->req.logon.user_name, netlogon->req.logon.acct_control, src->addr, netlogon->req.logon.nt_version, iface->nbtsrv->task->lp_ctx, &netlogon_response.data.samlogon, false); if (!NT_STATUS_IS_OK(status)) { DEBUG(2,("NBT netlogon query failed domain=%s sid=%s version=%d - %s\n", name->name, dom_sid_string(packet, sid), netlogon->req.logon.nt_version, nt_errstr(status))); return; } netlogon_response.response_type = NETLOGON_SAMLOGON; packet->data.msg.dest_name.type = 0; dgram_mailslot_netlogon_reply(reply_iface->dgmsock, packet, lpcfg_netbios_name(iface->nbtsrv->task->lp_ctx), netlogon->req.logon.mailslot_name, &netlogon_response); }
const char *dcesrv_common_get_server_name(TALLOC_CTX *mem_ctx, struct dcesrv_context *dce_ctx, const char *server_unc) { const char *p = server_unc; /* if there's no string return our NETBIOS name */ if (!p) { return talloc_strdup(mem_ctx, lpcfg_netbios_name(dce_ctx->lp_ctx)); } /* if there're '\\\\' in front remove them otherwise just pass the string */ if (p[0] == '\\' && p[1] == '\\') { p += 2; } return talloc_strdup(mem_ctx, p); }
/** see if a string matches either our primary or one of our secondary netbios aliases. do a case insensitive match */ bool lpcfg_is_myname(struct loadparm_context *lp_ctx, const char *name) { const char **aliases; int i; if (strcasecmp_m(name, lpcfg_netbios_name(lp_ctx)) == 0) { return true; } aliases = lpcfg_netbios_aliases(lp_ctx); for (i=0; aliases && aliases[i]; i++) { if (strcasecmp_m(name, aliases[i]) == 0) { return true; } } return false; }
NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, struct hdb_entry_ex *client, DATA_BLOB **_pac_blob) { struct samba_kdc_entry *p = talloc_get_type(client->ctx, struct samba_kdc_entry); struct auth_user_info_dc *user_info_dc; DATA_BLOB *pac_blob; NTSTATUS nt_status; /* The user account may be set not to want the PAC */ if ( ! samba_princ_needs_pac(client)) { *_pac_blob = NULL; return NT_STATUS_OK; } pac_blob = talloc_zero(mem_ctx, DATA_BLOB); if (!pac_blob) { return NT_STATUS_NO_MEMORY; } nt_status = authsam_make_user_info_dc(mem_ctx, p->kdc_db_ctx->samdb, lpcfg_netbios_name(p->kdc_db_ctx->lp_ctx), lpcfg_sam_name(p->kdc_db_ctx->lp_ctx), p->realm_dn, p->msg, data_blob(NULL, 0), data_blob(NULL, 0), &user_info_dc); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("Getting user info for PAC failed: %s\n", nt_errstr(nt_status))); return nt_status; } nt_status = samba_get_logon_info_pac_blob(mem_ctx, user_info_dc, pac_blob); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("Building PAC failed: %s\n", nt_errstr(nt_status))); return nt_status; } *_pac_blob = pac_blob; return NT_STATUS_OK; }
/** \details This function replaces network address from the binding strings returned by Exchange for the PR_EMS_AB_NETWORK_ADDRESS property and limit the binding strings scope to ncacn_ip_tcp. \param dce_call pointer to the session context \param r pointer to the NspiGetProps structure \return true on success, otherwise false */ bool mapiproxy_NspiGetProps(struct dcesrv_call_state *dce_call, struct NspiGetProps *r) { uint32_t i; uint32_t propID = -1; struct SPropTagArray *SPropTagArray = NULL; struct PropertyRow_r *Row; struct StringArray_r *slpstr; struct PropertyValue_r *lpProp; /* Sanity checks */ if (!r->out.ppRows) return false; if (!(*r->out.ppRows)->cValues) return false; /* Step 1. Find PR_EMS_AB_NETWORK_ADDRESS index */ propID = -1; SPropTagArray = r->in.pPropTags; for (i = 0; i < SPropTagArray->cValues; i++) { if (SPropTagArray->aulPropTag[i] == PR_EMS_AB_NETWORK_ADDRESS) { propID = i; break; } } if (propID == -1) return false; /* Step 2. Retrieve the SLPSTRArray */ Row = *r->out.ppRows; lpProp = &Row->lpProps[propID]; if (!lpProp) return false; if (lpProp->ulPropTag != PR_EMS_AB_NETWORK_ADDRESS) return false; slpstr = &(lpProp->value.MVszA); /* Step 3. Modify Exchange binding strings and only return ncacn_ip_tcp */ slpstr->cValues = 1; slpstr->lppszA[0] = talloc_asprintf(dce_call, "ncacn_ip_tcp:%s.%s", lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx), lpcfg_realm(dce_call->conn->dce_ctx->lp_ctx)); slpstr->lppszA[0] = strlower_talloc(dce_call, slpstr->lppszA[0]); return true; }
static bool torture_winbind_struct_netbios_name(struct torture_context *torture) { struct winbindd_response rep; const char *expected; ZERO_STRUCT(rep); torture_comment(torture, "Running WINBINDD_NETBIOS_NAME (struct based)\n"); DO_STRUCT_REQ_REP(WINBINDD_NETBIOS_NAME, NULL, &rep); expected = torture_setting_string(torture, "winbindd_netbios_name", lpcfg_netbios_name(torture->lp_ctx)); expected = strupper_talloc(torture, expected); torture_assert_str_equal(torture, rep.data.netbios_name, expected, "winbindd's netbios name doesn't match"); return true; }
/** \details exchange_ds_rfr RfrGetNewDSA (0x0) function \param dce_call pointer to the session context \param mem_ctx pointer to the memory context \param r pointer to the RfrGetNewDSA request data \note We incorrectly assume input pUserDN is correct and available, but it is OK for now. \return MAPI_E_SUCCESS on success */ static enum MAPISTATUS dcesrv_RfrGetNewDSA(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct RfrGetNewDSA *r) { const char *netbiosname = NULL; const char *realm = NULL; char *fqdn = NULL; OC_DEBUG(5, "exchange_ds_rfr: RfrGetNewDSA (0x0)"); /* Step 0. Ensure incoming user is authenticated */ if (!dcesrv_call_authenticated(dce_call)) { OC_DEBUG(1, "No challenge requested by client, cannot authenticate"); r->out.ppszUnused = NULL; r->out.ppszServer = NULL; r->out.result = MAPI_E_LOGON_FAILED; return MAPI_E_LOGON_FAILED; } /* Step 1. We don't have load-balancing support yet, just return Samba FQDN name */ netbiosname = lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx); realm = lpcfg_realm(dce_call->conn->dce_ctx->lp_ctx); if (!netbiosname || !realm) { r->out.ppszUnused = NULL; r->out.ppszServer = NULL; r->out.result = MAPI_E_NO_SUPPORT; return MAPI_E_NO_SUPPORT; } fqdn = talloc_asprintf(mem_ctx, "%s.%s", netbiosname, realm); r->out.ppszUnused = NULL; r->out.ppszServer = talloc_array(mem_ctx, const char *, 2); r->out.ppszServer[0] = strlower_talloc(mem_ctx, fqdn); r->out.ppszServer[1] = NULL; r->out.result = MAPI_E_SUCCESS; return MAPI_E_SUCCESS; }
/* startup the winbind task */ static void winbind_task_init(struct task_server *task) { uint16_t port = 1; const struct model_ops *model_ops; NTSTATUS status; struct wbsrv_service *service; struct wbsrv_listen_socket *listen_socket; char *errstring; struct dom_sid *primary_sid; bool ok; task_server_set_title(task, "task[winbind]"); /* within the winbind task we want to be a single process, so ask for the single process model ops and pass these to the stream_setup_socket() call. */ model_ops = process_model_startup("single"); if (!model_ops) { task_server_terminate(task, "Can't find 'single' process model_ops", true); return; } /* Make sure the directory for the Samba3 socket exists, and is of the correct permissions */ ok = directory_create_or_exist_strict(lpcfg_winbindd_socket_directory(task->lp_ctx), geteuid(), 0755); if (!ok) { task_server_terminate(task, "Cannot create winbindd pipe directory", true); return; } /* Make sure the directory for the Samba3 socket exists, and is of the correct permissions */ ok = directory_create_or_exist_strict(lpcfg_winbindd_privileged_socket_directory(task->lp_ctx), geteuid(), 0750); if (!ok) { task_server_terminate(task, "Cannot create winbindd privileged pipe directory", true); return; } service = talloc_zero(task, struct wbsrv_service); if (!service) goto nomem; service->task = task; /* Find the primary SID, depending if we are a standalone * server (what good is winbind in this case, but anyway...), * or are in a domain as a member or a DC */ switch (lpcfg_server_role(service->task->lp_ctx)) { case ROLE_STANDALONE: primary_sid = secrets_get_domain_sid(service, service->task->lp_ctx, lpcfg_netbios_name(service->task->lp_ctx), &service->sec_channel_type, &errstring); if (!primary_sid) { char *message = talloc_asprintf(task, "Cannot start Winbind (standalone configuration): %s: " "Have you provisioned this server (%s) or changed it's name?", errstring, lpcfg_netbios_name(service->task->lp_ctx)); task_server_terminate(task, message, true); return; } break; case ROLE_DOMAIN_MEMBER: primary_sid = secrets_get_domain_sid(service, service->task->lp_ctx, lpcfg_workgroup(service->task->lp_ctx), &service->sec_channel_type, &errstring); if (!primary_sid) { char *message = talloc_asprintf(task, "Cannot start Winbind (domain member): %s: " "Have you joined the %s domain?", errstring, lpcfg_workgroup(service->task->lp_ctx)); task_server_terminate(task, message, true); return; } break; case ROLE_ACTIVE_DIRECTORY_DC: primary_sid = secrets_get_domain_sid(service, service->task->lp_ctx, lpcfg_workgroup(service->task->lp_ctx), &service->sec_channel_type, &errstring); if (!primary_sid) { char *message = talloc_asprintf(task, "Cannot start Winbind (domain controller): %s: " "Have you provisioned the %s domain?", errstring, lpcfg_workgroup(service->task->lp_ctx)); task_server_terminate(task, message, true); return; } break; case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: task_server_terminate(task, "Cannot start 'samba' winbindd as a 'classic samba' DC: use winbindd instead", true); return; } service->primary_sid = primary_sid; service->idmap_ctx = idmap_init(service, task->event_ctx, task->lp_ctx); if (service->idmap_ctx == NULL) { task_server_terminate(task, "Failed to load idmap database", true); return; } service->priv_pipe_dir = lpcfg_winbindd_privileged_socket_directory(task->lp_ctx); service->pipe_dir = lpcfg_winbindd_socket_directory(task->lp_ctx); /* setup the unprivileged samba3 socket */ listen_socket = talloc(service, struct wbsrv_listen_socket); if (!listen_socket) goto nomem; listen_socket->socket_path = talloc_asprintf(listen_socket, "%s/%s", service->pipe_dir, WINBINDD_SOCKET_NAME); if (!listen_socket->socket_path) goto nomem; listen_socket->service = service; listen_socket->privileged = false; status = stream_setup_socket(task, task->event_ctx, task->lp_ctx, model_ops, &wbsrv_ops, "unix", listen_socket->socket_path, &port, lpcfg_socket_options(task->lp_ctx), listen_socket); if (!NT_STATUS_IS_OK(status)) goto listen_failed; /* setup the privileged samba3 socket */ listen_socket = talloc(service, struct wbsrv_listen_socket); if (!listen_socket) goto nomem; listen_socket->socket_path = talloc_asprintf(listen_socket, "%s/%s", service->priv_pipe_dir, WINBINDD_SOCKET_NAME); if (!listen_socket->socket_path) goto nomem; listen_socket->service = service; listen_socket->privileged = true; status = stream_setup_socket(task, task->event_ctx, task->lp_ctx, model_ops, &wbsrv_ops, "unix", listen_socket->socket_path, &port, lpcfg_socket_options(task->lp_ctx), listen_socket); if (!NT_STATUS_IS_OK(status)) goto listen_failed; status = wbsrv_init_irpc(service); if (!NT_STATUS_IS_OK(status)) goto irpc_failed; return; listen_failed: DEBUG(0,("stream_setup_socket(path=%s) failed - %s\n", listen_socket->socket_path, nt_errstr(status))); task_server_terminate(task, nt_errstr(status), true); return; irpc_failed: DEBUG(0,("wbsrv_init_irpc() failed - %s\n", nt_errstr(status))); task_server_terminate(task, nt_errstr(status), true); return; nomem: task_server_terminate(task, nt_errstr(NT_STATUS_NO_MEMORY), true); return; }
/* connect to a share - used when a tree_connect operation comes in. */ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, union smb_tcon *tcon) { NTSTATUS status; struct cvfs_private *p; const char *host, *user, *pass, *domain, *remote_share; struct smb_composite_connect io; struct composite_context *creq; struct share_config *scfg = ntvfs->ctx->config; struct cli_credentials *credentials; bool machine_account; bool s4u2proxy; const char* sharename; switch (tcon->generic.level) { case RAW_TCON_TCON: sharename = tcon->tcon.in.service; break; case RAW_TCON_TCONX: sharename = tcon->tconx.in.path; break; case RAW_TCON_SMB2: sharename = tcon->smb2.in.path; break; default: return NT_STATUS_INVALID_LEVEL; } if (strncmp(sharename, "\\\\", 2) == 0) { char *str = strchr(sharename+2, '\\'); if (str) { sharename = str + 1; } } /* Here we need to determine which server to connect to. * For now we use parametric options, type cifs. * Later we will use security=server and auth_server.c. */ host = share_string_option(scfg, CIFS_SERVER, NULL); user = share_string_option(scfg, CIFS_USER, NULL); pass = share_string_option(scfg, CIFS_PASSWORD, NULL); domain = share_string_option(scfg, CIFS_DOMAIN, NULL); remote_share = share_string_option(scfg, CIFS_SHARE, NULL); if (!remote_share) { remote_share = sharename; } machine_account = share_bool_option(scfg, CIFS_USE_MACHINE_ACCT, CIFS_USE_MACHINE_ACCT_DEFAULT); s4u2proxy = share_bool_option(scfg, CIFS_USE_S4U2PROXY, CIFS_USE_S4U2PROXY_DEFAULT); p = talloc_zero(ntvfs, struct cvfs_private); if (!p) { return NT_STATUS_NO_MEMORY; } ntvfs->private_data = p; if (!host) { DEBUG(1,("CIFS backend: You must supply server\n")); return NT_STATUS_INVALID_PARAMETER; } if (user && pass) { DEBUG(5, ("CIFS backend: Using specified password\n")); credentials = cli_credentials_init(p); if (!credentials) { return NT_STATUS_NO_MEMORY; } cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx); cli_credentials_set_username(credentials, user, CRED_SPECIFIED); if (domain) { cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED); } cli_credentials_set_password(credentials, pass, CRED_SPECIFIED); } else if (machine_account) { DEBUG(5, ("CIFS backend: Using machine account\n")); credentials = cli_credentials_init(p); cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx); if (domain) { cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED); } status = cli_credentials_set_machine_account(credentials, ntvfs->ctx->lp_ctx); if (!NT_STATUS_IS_OK(status)) { return status; } } else if (req->session_info->credentials) { DEBUG(5, ("CIFS backend: Using delegated credentials\n")); credentials = req->session_info->credentials; } else if (s4u2proxy) { struct ccache_container *ccc = NULL; const char *err_str = NULL; int ret; char *impersonate_principal; char *self_service; char *target_service; impersonate_principal = talloc_asprintf(req, "%s@%s", req->session_info->info->account_name, req->session_info->info->domain_name); self_service = talloc_asprintf(req, "cifs/%s", lpcfg_netbios_name(ntvfs->ctx->lp_ctx)); target_service = talloc_asprintf(req, "cifs/%s", host); DEBUG(5, ("CIFS backend: Using S4U2Proxy credentials\n")); credentials = cli_credentials_init(p); cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx); if (domain) { cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED); } status = cli_credentials_set_machine_account(credentials, ntvfs->ctx->lp_ctx); if (!NT_STATUS_IS_OK(status)) { return status; } cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED); cli_credentials_set_impersonate_principal(credentials, impersonate_principal, self_service); cli_credentials_set_target_service(credentials, target_service); ret = cli_credentials_get_ccache(credentials, ntvfs->ctx->event_ctx, ntvfs->ctx->lp_ctx, &ccc, &err_str); if (ret != 0) { status = NT_STATUS_CROSSREALM_DELEGATION_FAILURE; DEBUG(1,("S4U2Proxy: cli_credentials_get_ccache() gave: ret[%d] str[%s] - %s\n", ret, err_str, nt_errstr(status))); return status; } } else { DEBUG(1,("CIFS backend: NO delegated credentials found: You must supply server, user and password or the client must supply delegated credentials\n")); return NT_STATUS_INTERNAL_ERROR; } /* connect to the server, using the smbd event context */ io.in.dest_host = host; io.in.dest_ports = lpcfg_smb_ports(ntvfs->ctx->lp_ctx); io.in.socket_options = lpcfg_socket_options(ntvfs->ctx->lp_ctx); io.in.called_name = host; io.in.credentials = credentials; io.in.fallback_to_anonymous = false; io.in.workgroup = lpcfg_workgroup(ntvfs->ctx->lp_ctx); io.in.service = remote_share; io.in.service_type = "?????"; io.in.gensec_settings = lpcfg_gensec_settings(p, ntvfs->ctx->lp_ctx); lpcfg_smbcli_options(ntvfs->ctx->lp_ctx, &io.in.options); lpcfg_smbcli_session_options(ntvfs->ctx->lp_ctx, &io.in.session_options); if (!(ntvfs->ctx->client_caps & NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS)) { io.in.options.use_level2_oplocks = false; } creq = smb_composite_connect_send(&io, p, lpcfg_resolve_context(ntvfs->ctx->lp_ctx), ntvfs->ctx->event_ctx); status = smb_composite_connect_recv(creq, p); NT_STATUS_NOT_OK_RETURN(status); p->tree = io.out.tree; p->transport = p->tree->session->transport; SETUP_PID; p->ntvfs = ntvfs; ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "NTFS"); NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type); ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:"); NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type); if (tcon->generic.level == RAW_TCON_TCONX) { tcon->tconx.out.fs_type = ntvfs->ctx->fs_type; tcon->tconx.out.dev_type = ntvfs->ctx->dev_type; } /* we need to receive oplock break requests from the server */ smbcli_oplock_handler(p->transport, oplock_handler, p); p->map_generic = share_bool_option(scfg, CIFS_MAP_GENERIC, CIFS_MAP_GENERIC_DEFAULT); p->map_trans2 = share_bool_option(scfg, CIFS_MAP_TRANS2, CIFS_MAP_TRANS2_DEFAULT); return NT_STATUS_OK; }
/* format a record for bind9 */ static bool b9_format(struct dlz_bind9_data *state, TALLOC_CTX *mem_ctx, struct dnsp_DnssrvRpcRecord *rec, const char **type, const char **data) { switch (rec->wType) { case DNS_TYPE_A: *type = "a"; *data = rec->data.ipv4; break; case DNS_TYPE_AAAA: *type = "aaaa"; *data = rec->data.ipv6; break; case DNS_TYPE_CNAME: *type = "cname"; *data = rec->data.cname; break; case DNS_TYPE_TXT: *type = "txt"; *data = rec->data.txt; break; case DNS_TYPE_PTR: *type = "ptr"; *data = rec->data.ptr; break; case DNS_TYPE_SRV: *type = "srv"; *data = talloc_asprintf(mem_ctx, "%u %u %u %s", rec->data.srv.wPriority, rec->data.srv.wWeight, rec->data.srv.wPort, rec->data.srv.nameTarget); break; case DNS_TYPE_MX: *type = "mx"; *data = talloc_asprintf(mem_ctx, "%u %s", rec->data.mx.wPriority, rec->data.mx.nameTarget); break; case DNS_TYPE_HINFO: *type = "hinfo"; *data = talloc_asprintf(mem_ctx, "%s %s", rec->data.hinfo.cpu, rec->data.hinfo.os); break; case DNS_TYPE_NS: *type = "ns"; *data = rec->data.ns; break; case DNS_TYPE_SOA: { const char *mname; *type = "soa"; /* we need to fake the authoritative nameserver to * point at ourselves. This is how AD DNS servers * force clients to send updates to the right local DC */ mname = talloc_asprintf(mem_ctx, "%s.%s", lpcfg_netbios_name(state->lp), lpcfg_dnsdomain(state->lp)); if (mname == NULL) { return false; } mname = strlower_talloc(mem_ctx, mname); if (mname == NULL) { return false; } state->soa_serial = rec->data.soa.serial; *data = talloc_asprintf(mem_ctx, "%s %s %u %u %u %u %u", mname, rec->data.soa.rname, rec->data.soa.serial, rec->data.soa.refresh, rec->data.soa.retry, rec->data.soa.expire, rec->data.soa.minimum); break; } default: state->log(ISC_LOG_ERROR, "samba b9_putrr: unhandled record type %u", rec->wType); return false; } return true; }
},{ .version = WITNESS_V2, .expected_status = NT_STATUS_OK, .expected_result = WERR_REVISION_MISMATCH },{ .version = WITNESS_V1, .net_name = "", .ip_address = "", .client_computer_name = "", .expected_status = NT_STATUS_OK, .expected_result = WERR_INVALID_PARAMETER },{ .version = WITNESS_V1, .net_name = NULL, .ip_address = NULL, .client_computer_name = lpcfg_netbios_name(tctx->lp_ctx), .expected_status = NT_STATUS_OK, .expected_result = WERR_INVALID_PARAMETER },{ .version = WITNESS_V2, .net_name = NULL, .ip_address = NULL, .client_computer_name = lpcfg_netbios_name(tctx->lp_ctx), .expected_status = NT_STATUS_OK, .expected_result = WERR_REVISION_MISMATCH },{ .version = WITNESS_V1, .net_name = dcerpc_server_name(p), .ip_address = NULL, .client_computer_name = lpcfg_netbios_name(tctx->lp_ctx), .expected_status = NT_STATUS_OK,
static WERROR sptr_PrintServerData(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, const char *value_name, union spoolss_PrinterData *r, enum winreg_Type *type) { struct dcerpc_server_info *server_info = lpcfg_dcerpc_server_info(mem_ctx, server->ntptr->lp_ctx); if (strcmp("W3SvcInstalled", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("BeepEnabled", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("EventLog", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("NetPopup", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("NetPopupToComputer", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("MajorVersion", value_name) == 0) { *type = REG_DWORD; r->value = 3; return WERR_OK; } else if (strcmp("MinorVersion", value_name) == 0) { *type = REG_DWORD; r->value = 0; return WERR_OK; } else if (strcmp("DefaultSpoolDirectory", value_name) == 0) { *type = REG_SZ; r->string = "C:\\PRINTERS"; return WERR_OK; } else if (strcmp("Architecture", value_name) == 0) { *type = REG_SZ; r->string = SPOOLSS_ARCHITECTURE_NT_X86; return WERR_OK; } else if (strcmp("DsPresent", value_name) == 0) { *type = REG_DWORD; r->value = 1; return WERR_OK; } else if (strcmp("OSVersion", value_name) == 0) { DATA_BLOB blob; enum ndr_err_code ndr_err; struct spoolss_OSVersion os; os.major = server_info->version_major; os.minor = server_info->version_minor; os.build = server_info->version_build; os.extra_string = ""; ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os, (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return WERR_GENERAL_FAILURE; } *type = REG_BINARY; r->binary = blob; return WERR_OK; } else if (strcmp("OSVersionEx", value_name) == 0) { DATA_BLOB blob; enum ndr_err_code ndr_err; struct spoolss_OSVersionEx os_ex; os_ex.major = server_info->version_major; os_ex.minor = server_info->version_minor; os_ex.build = server_info->version_build; os_ex.extra_string = ""; os_ex.service_pack_major= 0; os_ex.service_pack_minor= 0; os_ex.suite_mask = 0; os_ex.product_type = 0; os_ex.reserved = 0; ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os_ex, (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersionEx); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return WERR_GENERAL_FAILURE; } *type = REG_BINARY; r->binary = blob; return WERR_OK; } else if (strcmp("DNSMachineName", value_name) == 0) { const char *dnsdomain = lpcfg_dnsdomain(server->ntptr->lp_ctx); if (dnsdomain == NULL) return WERR_INVALID_PARAM; *type = REG_SZ; r->string = talloc_asprintf(mem_ctx, "%s.%s", lpcfg_netbios_name(server->ntptr->lp_ctx), dnsdomain); W_ERROR_HAVE_NO_MEMORY(r->string); return WERR_OK; } return WERR_INVALID_PARAM; }
static void manage_ntlm_server_1_request(enum stdio_helper_mode stdio_helper_mode, struct loadparm_context *lp_ctx, char *buf, int length, void **private1, unsigned int mux_id, void **private2) { char *request, *parameter; static DATA_BLOB challenge; static DATA_BLOB lm_response; static DATA_BLOB nt_response; static char *full_username; static char *username; static char *domain; static char *plaintext_password; static bool ntlm_server_1_user_session_key; static bool ntlm_server_1_lm_session_key; if (strequal(buf, ".")) { if (!full_username && !username) { mux_printf(mux_id, "Error: No username supplied!\n"); } else if (plaintext_password) { /* handle this request as plaintext */ if (!full_username) { if (asprintf(&full_username, "%s%c%s", domain, *lpcfg_winbind_separator(lp_ctx), username) < 0) { mux_printf(mux_id, "Error: Out of memory in asprintf!\n.\n"); return; } } if (check_plaintext_auth(full_username, plaintext_password, false)) { mux_printf(mux_id, "Authenticated: Yes\n"); } else { mux_printf(mux_id, "Authenticated: No\n"); } } else if (!lm_response.data && !nt_response.data) { mux_printf(mux_id, "Error: No password supplied!\n"); } else if (!challenge.data) { mux_printf(mux_id, "Error: No lanman-challenge supplied!\n"); } else { char *error_string = NULL; DATA_BLOB lm_key; DATA_BLOB user_session_key; uint32_t flags = 0; if (full_username && !username) { SAFE_FREE(username); SAFE_FREE(domain); if (!parse_ntlm_auth_domain_user(full_username, &username, &domain, *lpcfg_winbind_separator(lp_ctx))) { /* username might be 'tainted', don't print into our new-line deleimianted stream */ mux_printf(mux_id, "Error: Could not parse into domain and username\n"); } } if (!domain) { domain = smb_xstrdup(lpcfg_workgroup(lp_ctx)); } if (ntlm_server_1_lm_session_key) flags |= NTLM_AUTH_FLAG_LMKEY; if (ntlm_server_1_user_session_key) flags |= NTLM_AUTH_FLAG_USER_SESSION_KEY; if (!NT_STATUS_IS_OK( local_pw_check_specified(lp_ctx, username, domain, lpcfg_netbios_name(lp_ctx), &challenge, &lm_response, &nt_response, flags, &lm_key, &user_session_key, &error_string, NULL))) { mux_printf(mux_id, "Authenticated: No\n"); mux_printf(mux_id, "Authentication-Error: %s\n.\n", error_string); SAFE_FREE(error_string); } else { static char zeros[16]; char *hex_lm_key; char *hex_user_session_key; mux_printf(mux_id, "Authenticated: Yes\n"); if (ntlm_server_1_lm_session_key && lm_key.length && (memcmp(zeros, lm_key.data, lm_key.length) != 0)) { hex_encode(lm_key.data, lm_key.length, &hex_lm_key); mux_printf(mux_id, "LANMAN-Session-Key: %s\n", hex_lm_key); SAFE_FREE(hex_lm_key); } if (ntlm_server_1_user_session_key && user_session_key.length && (memcmp(zeros, user_session_key.data, user_session_key.length) != 0)) { hex_encode(user_session_key.data, user_session_key.length, &hex_user_session_key); mux_printf(mux_id, "User-Session-Key: %s\n", hex_user_session_key); SAFE_FREE(hex_user_session_key); } } } /* clear out the state */ challenge = data_blob(NULL, 0); nt_response = data_blob(NULL, 0); lm_response = data_blob(NULL, 0); SAFE_FREE(full_username); SAFE_FREE(username); SAFE_FREE(domain); SAFE_FREE(plaintext_password); ntlm_server_1_user_session_key = false; ntlm_server_1_lm_session_key = false; mux_printf(mux_id, ".\n"); return; } request = buf; /* Indicates a base64 encoded structure */ parameter = strstr(request, ":: "); if (!parameter) { parameter = strstr(request, ": "); if (!parameter) { DEBUG(0, ("Parameter not found!\n")); mux_printf(mux_id, "Error: Parameter not found!\n.\n"); return; } parameter[0] ='\0'; parameter++; parameter[0] ='\0'; parameter++; } else { parameter[0] ='\0'; parameter++; parameter[0] ='\0'; parameter++; parameter[0] ='\0'; parameter++; base64_decode_inplace(parameter); } if (strequal(request, "LANMAN-Challenge")) { challenge = strhex_to_data_blob(NULL, parameter); if (challenge.length != 8) { mux_printf(mux_id, "Error: hex decode of %s failed! (got %d bytes, expected 8)\n.\n", parameter, (int)challenge.length); challenge = data_blob(NULL, 0); } } else if (strequal(request, "NT-Response")) { nt_response = strhex_to_data_blob(NULL, parameter); if (nt_response.length < 24) { mux_printf(mux_id, "Error: hex decode of %s failed! (only got %d bytes, needed at least 24)\n.\n", parameter, (int)nt_response.length); nt_response = data_blob(NULL, 0); } } else if (strequal(request, "LANMAN-Response")) { lm_response = strhex_to_data_blob(NULL, parameter); if (lm_response.length != 24) { mux_printf(mux_id, "Error: hex decode of %s failed! (got %d bytes, expected 24)\n.\n", parameter, (int)lm_response.length); lm_response = data_blob(NULL, 0); } } else if (strequal(request, "Password")) { plaintext_password = smb_xstrdup(parameter); } else if (strequal(request, "NT-Domain")) { domain = smb_xstrdup(parameter); } else if (strequal(request, "Username")) { username = smb_xstrdup(parameter); } else if (strequal(request, "Full-Username")) { full_username = smb_xstrdup(parameter); } else if (strequal(request, "Request-User-Session-Key")) { ntlm_server_1_user_session_key = strequal(parameter, "Yes"); } else if (strequal(request, "Request-LanMan-Session-Key")) { ntlm_server_1_lm_session_key = strequal(parameter, "Yes"); } else { mux_printf(mux_id, "Error: Unknown request %s\n.\n", request); } }
/** * Start NTLMSSP on the server side * */ NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security) { NTSTATUS nt_status; struct ntlmssp_state *ntlmssp_state; struct gensec_ntlmssp_context *gensec_ntlmssp; const char *netbios_name; const char *netbios_domain; const char *dns_name; const char *dns_domain; enum server_role role; role = lpcfg_server_role(gensec_security->settings->lp_ctx); nt_status = gensec_ntlmssp_start(gensec_security); NT_STATUS_NOT_OK_RETURN(nt_status); gensec_ntlmssp = talloc_get_type_abort(gensec_security->private_data, struct gensec_ntlmssp_context); ntlmssp_state = talloc_zero(gensec_ntlmssp, struct ntlmssp_state); if (!ntlmssp_state) { return NT_STATUS_NO_MEMORY; } gensec_ntlmssp->ntlmssp_state = ntlmssp_state; ntlmssp_state->role = NTLMSSP_SERVER; ntlmssp_state->expected_state = NTLMSSP_NEGOTIATE; ntlmssp_state->allow_lm_response = lpcfg_lanman_auth(gensec_security->settings->lp_ctx); if (ntlmssp_state->allow_lm_response && gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "allow_lm_key", false)) { ntlmssp_state->allow_lm_key = true; } ntlmssp_state->force_old_spnego = false; if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "force_old_spnego", false)) { /* * For testing Windows 2000 mode */ ntlmssp_state->force_old_spnego = true; } ntlmssp_state->neg_flags = NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_VERSION; if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "128bit", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_128; } if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "56bit", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56; } if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "keyexchange", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_KEY_EXCH; } if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "alwayssign", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; } if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "ntlm2", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2; } if (ntlmssp_state->allow_lm_key) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY; } /* * We always allow NTLMSSP_NEGOTIATE_SIGN and NTLMSSP_NEGOTIATE_SEAL. * * These will be removed if the client doesn't want them. */ ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; } if (gensec_security->want_features & GENSEC_FEATURE_SIGN) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; if (gensec_security->want_features & GENSEC_FEATURE_LDAP_STYLE) { /* * We need to handle NTLMSSP_NEGOTIATE_SIGN as * NTLMSSP_NEGOTIATE_SEAL if GENSEC_FEATURE_LDAP_STYLE * is requested. */ ntlmssp_state->force_wrap_seal = true; } } if (gensec_security->want_features & GENSEC_FEATURE_SEAL) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; } if (role == ROLE_STANDALONE) { ntlmssp_state->server.is_standalone = true; } else { ntlmssp_state->server.is_standalone = false; } if (gensec_security->settings->server_netbios_name) { netbios_name = gensec_security->settings->server_netbios_name; } else { netbios_name = lpcfg_netbios_name(gensec_security->settings->lp_ctx); } if (gensec_security->settings->server_netbios_domain) { netbios_domain = gensec_security->settings->server_netbios_domain; } else { netbios_domain = lpcfg_workgroup(gensec_security->settings->lp_ctx); } if (gensec_security->settings->server_dns_name) { dns_name = gensec_security->settings->server_dns_name; } else { const char *dnsdomain = lpcfg_dnsdomain(gensec_security->settings->lp_ctx); char *lower_netbiosname; lower_netbiosname = strlower_talloc(ntlmssp_state, netbios_name); NT_STATUS_HAVE_NO_MEMORY(lower_netbiosname); /* Find out the DNS host name */ if (dnsdomain && dnsdomain[0] != '\0') { dns_name = talloc_asprintf(ntlmssp_state, "%s.%s", lower_netbiosname, dnsdomain); talloc_free(lower_netbiosname); NT_STATUS_HAVE_NO_MEMORY(dns_name); } else { dns_name = lower_netbiosname; } } if (gensec_security->settings->server_dns_domain) { dns_domain = gensec_security->settings->server_dns_domain; } else { dns_domain = lpcfg_dnsdomain(gensec_security->settings->lp_ctx); } ntlmssp_state->server.netbios_name = talloc_strdup(ntlmssp_state, netbios_name); NT_STATUS_HAVE_NO_MEMORY(ntlmssp_state->server.netbios_name); ntlmssp_state->server.netbios_domain = talloc_strdup(ntlmssp_state, netbios_domain); NT_STATUS_HAVE_NO_MEMORY(ntlmssp_state->server.netbios_domain); ntlmssp_state->server.dns_name = talloc_strdup(ntlmssp_state, dns_name); NT_STATUS_HAVE_NO_MEMORY(ntlmssp_state->server.dns_name); ntlmssp_state->server.dns_domain = talloc_strdup(ntlmssp_state, dns_domain); NT_STATUS_HAVE_NO_MEMORY(ntlmssp_state->server.dns_domain); ntlmssp_state->neg_flags |= ntlmssp_state->required_flags; ntlmssp_state->conf_flags = ntlmssp_state->neg_flags; return NT_STATUS_OK; }
NTSTATUS encrypt_user_info(TALLOC_CTX *mem_ctx, struct auth4_context *auth_context, enum auth_password_state to_state, const struct auth_usersupplied_info *user_info_in, const struct auth_usersupplied_info **user_info_encrypted) { NTSTATUS nt_status; struct auth_usersupplied_info *user_info_temp; switch (to_state) { case AUTH_PASSWORD_RESPONSE: switch (user_info_in->password_state) { case AUTH_PASSWORD_PLAIN: { const struct auth_usersupplied_info *user_info_temp2; nt_status = encrypt_user_info(mem_ctx, auth_context, AUTH_PASSWORD_HASH, user_info_in, &user_info_temp2); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } user_info_in = user_info_temp2; /* fall through */ } case AUTH_PASSWORD_HASH: { uint8_t chal[8]; DATA_BLOB chall_blob; user_info_temp = talloc_zero(mem_ctx, struct auth_usersupplied_info); if (!user_info_temp) { return NT_STATUS_NO_MEMORY; } if (!talloc_reference(user_info_temp, user_info_in)) { return NT_STATUS_NO_MEMORY; } *user_info_temp = *user_info_in; user_info_temp->mapped_state = to_state; nt_status = auth_get_challenge(auth_context, chal); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } chall_blob = data_blob_talloc(mem_ctx, chal, 8); if (lpcfg_client_ntlmv2_auth(auth_context->lp_ctx)) { DATA_BLOB names_blob = NTLMv2_generate_names_blob(mem_ctx, lpcfg_netbios_name(auth_context->lp_ctx), lpcfg_workgroup(auth_context->lp_ctx)); DATA_BLOB lmv2_response, ntlmv2_response, lmv2_session_key, ntlmv2_session_key; if (!SMBNTLMv2encrypt_hash(user_info_temp, user_info_in->client.account_name, user_info_in->client.domain_name, user_info_in->password.hash.nt->hash, &chall_blob, NULL, /* server_timestamp */ &names_blob, &lmv2_response, &ntlmv2_response, &lmv2_session_key, &ntlmv2_session_key)) { data_blob_free(&names_blob); return NT_STATUS_NO_MEMORY; } data_blob_free(&names_blob); user_info_temp->password.response.lanman = lmv2_response; user_info_temp->password.response.nt = ntlmv2_response; data_blob_free(&lmv2_session_key); data_blob_free(&ntlmv2_session_key); } else { DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, 24); SMBOWFencrypt(user_info_in->password.hash.nt->hash, chal, blob.data); user_info_temp->password.response.nt = blob; if (lpcfg_client_lanman_auth(auth_context->lp_ctx) && user_info_in->password.hash.lanman) { DATA_BLOB lm_blob = data_blob_talloc(mem_ctx, NULL, 24); SMBOWFencrypt(user_info_in->password.hash.lanman->hash, chal, blob.data); user_info_temp->password.response.lanman = lm_blob; } else { /* if not sending the LM password, send the NT password twice */ user_info_temp->password.response.lanman = user_info_temp->password.response.nt; } } user_info_in = user_info_temp; /* fall through */ } case AUTH_PASSWORD_RESPONSE: *user_info_encrypted = user_info_in; } break; case AUTH_PASSWORD_HASH: { switch (user_info_in->password_state) { case AUTH_PASSWORD_PLAIN: { struct samr_Password lanman; struct samr_Password nt; user_info_temp = talloc_zero(mem_ctx, struct auth_usersupplied_info); if (!user_info_temp) { return NT_STATUS_NO_MEMORY; } if (!talloc_reference(user_info_temp, user_info_in)) { return NT_STATUS_NO_MEMORY; } *user_info_temp = *user_info_in; user_info_temp->mapped_state = to_state; if (E_deshash(user_info_in->password.plaintext, lanman.hash)) { user_info_temp->password.hash.lanman = talloc(user_info_temp, struct samr_Password); *user_info_temp->password.hash.lanman = lanman; } else { user_info_temp->password.hash.lanman = NULL; } E_md4hash(user_info_in->password.plaintext, nt.hash); user_info_temp->password.hash.nt = talloc(user_info_temp, struct samr_Password); *user_info_temp->password.hash.nt = nt; user_info_in = user_info_temp; /* fall through */ } case AUTH_PASSWORD_HASH: *user_info_encrypted = user_info_in; break; default: return NT_STATUS_INVALID_PARAMETER; break; } break; }
/** * Start NTLMSSP on the server side * */ NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security) { NTSTATUS nt_status; struct ntlmssp_state *ntlmssp_state; struct gensec_ntlmssp_context *gensec_ntlmssp; nt_status = gensec_ntlmssp_start(gensec_security); NT_STATUS_NOT_OK_RETURN(nt_status); gensec_ntlmssp = talloc_get_type_abort(gensec_security->private_data, struct gensec_ntlmssp_context); ntlmssp_state = gensec_ntlmssp->ntlmssp_state; ntlmssp_state->role = NTLMSSP_SERVER; ntlmssp_state->expected_state = NTLMSSP_NEGOTIATE; ntlmssp_state->allow_lm_key = (lpcfg_lanman_auth(gensec_security->settings->lp_ctx) && gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "allow_lm_key", false)); ntlmssp_state->neg_flags = NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_VERSION; ntlmssp_state->lm_resp = data_blob(NULL, 0); ntlmssp_state->nt_resp = data_blob(NULL, 0); if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "128bit", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_128; } if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "56bit", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56; } if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "keyexchange", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_KEY_EXCH; } if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "alwayssign", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; } if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "ntlm2", true)) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2; } if (gensec_security->want_features & GENSEC_FEATURE_SIGN) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; } if (gensec_security->want_features & GENSEC_FEATURE_SEAL) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; } ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge; ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge; ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge; ntlmssp_state->check_password = auth_ntlmssp_check_password; if (lpcfg_server_role(gensec_security->settings->lp_ctx) == ROLE_STANDALONE) { ntlmssp_state->server.is_standalone = true; } else { ntlmssp_state->server.is_standalone = false; } ntlmssp_state->server.netbios_name = lpcfg_netbios_name(gensec_security->settings->lp_ctx); ntlmssp_state->server.netbios_domain = lpcfg_workgroup(gensec_security->settings->lp_ctx); { const char *dnsdomain = lpcfg_dnsdomain(gensec_security->settings->lp_ctx); char *dnsname, *lower_netbiosname; lower_netbiosname = strlower_talloc(ntlmssp_state, ntlmssp_state->server.netbios_name); /* Find out the DNS host name */ if (dnsdomain && dnsdomain[0] != '\0') { dnsname = talloc_asprintf(ntlmssp_state, "%s.%s", lower_netbiosname, dnsdomain); talloc_free(lower_netbiosname); ntlmssp_state->server.dns_name = dnsname; } else { ntlmssp_state->server.dns_name = lower_netbiosname; } NT_STATUS_HAVE_NO_MEMORY(ntlmssp_state->server.dns_name); ntlmssp_state->server.dns_domain = talloc_strdup(ntlmssp_state, lpcfg_dnsdomain(gensec_security->settings->lp_ctx)); NT_STATUS_HAVE_NO_MEMORY(ntlmssp_state->server.dns_domain); } return NT_STATUS_OK; }
/* fill in the cldap netlogon union for a given version */ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, const char *domain, const char *netbios_domain, struct dom_sid *domain_sid, const char *domain_guid, const char *user, uint32_t acct_control, const char *src_address, uint32_t version, struct loadparm_context *lp_ctx, struct netlogon_samlogon_response *netlogon, bool fill_on_blank_request) { const char *dom_attrs[] = {"objectGUID", NULL}; const char *none_attrs[] = {NULL}; struct ldb_result *dom_res = NULL, *user_res = NULL; int ret; const char **services = lpcfg_server_services(lp_ctx); uint32_t server_type; const char *pdc_name; struct GUID domain_uuid; const char *dns_domain; const char *forest_domain; const char *pdc_dns_name; const char *flatname; const char *server_site; const char *client_site; const char *pdc_ip; struct ldb_dn *domain_dn = NULL; struct interface *ifaces; bool user_known, am_rodc; NTSTATUS status; /* the domain parameter could have an optional trailing "." */ if (domain && domain[strlen(domain)-1] == '.') { domain = talloc_strndup(mem_ctx, domain, strlen(domain)-1); NT_STATUS_HAVE_NO_MEMORY(domain); } /* Lookup using long or short domainname */ if (domain && (strcasecmp_m(domain, lpcfg_dnsdomain(lp_ctx)) == 0)) { domain_dn = ldb_get_default_basedn(sam_ctx); } if (netbios_domain && (strcasecmp_m(netbios_domain, lpcfg_sam_name(lp_ctx)) == 0)) { domain_dn = ldb_get_default_basedn(sam_ctx); } if (domain_dn) { const char *domain_identifier = domain != NULL ? domain : netbios_domain; ret = ldb_search(sam_ctx, mem_ctx, &dom_res, domain_dn, LDB_SCOPE_BASE, dom_attrs, "objectClass=domain"); if (ret != LDB_SUCCESS) { DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", domain_identifier, ldb_dn_get_linearized(domain_dn), ldb_errstring(sam_ctx))); return NT_STATUS_NO_SUCH_DOMAIN; } if (dom_res->count != 1) { DEBUG(2,("Error finding domain '%s'/'%s' in sam\n", domain_identifier, ldb_dn_get_linearized(domain_dn))); return NT_STATUS_NO_SUCH_DOMAIN; } } /* Lookup using GUID or SID */ if ((dom_res == NULL) && (domain_guid || domain_sid)) { if (domain_guid) { struct GUID binary_guid; struct ldb_val guid_val; /* By this means, we ensure we don't have funny stuff in the GUID */ status = GUID_from_string(domain_guid, &binary_guid); if (!NT_STATUS_IS_OK(status)) { return status; } /* And this gets the result into the binary format we want anyway */ status = GUID_to_ndr_blob(&binary_guid, mem_ctx, &guid_val); if (!NT_STATUS_IS_OK(status)) { return status; } ret = ldb_search(sam_ctx, mem_ctx, &dom_res, NULL, LDB_SCOPE_SUBTREE, dom_attrs, "(&(objectCategory=DomainDNS)(objectGUID=%s))", ldb_binary_encode(mem_ctx, guid_val)); } else { /* domain_sid case */ ret = ldb_search(sam_ctx, mem_ctx, &dom_res, NULL, LDB_SCOPE_SUBTREE, dom_attrs, "(&(objectCategory=DomainDNS)(objectSid=%s))", dom_sid_string(mem_ctx, domain_sid)); } if (ret != LDB_SUCCESS) { DEBUG(2,("Unable to find a correct reference to GUID '%s' or SID '%s' in sam: %s\n", domain_guid, dom_sid_string(mem_ctx, domain_sid), ldb_errstring(sam_ctx))); return NT_STATUS_NO_SUCH_DOMAIN; } else if (dom_res->count == 1) { /* Ok, now just check it is our domain */ if (ldb_dn_compare(ldb_get_default_basedn(sam_ctx), dom_res->msgs[0]->dn) != 0) { DEBUG(2,("The GUID '%s' or SID '%s' doesn't identify our domain\n", domain_guid, dom_sid_string(mem_ctx, domain_sid))); return NT_STATUS_NO_SUCH_DOMAIN; } } else { DEBUG(2,("Unable to find a correct reference to GUID '%s' or SID '%s' in sam\n", domain_guid, dom_sid_string(mem_ctx, domain_sid))); return NT_STATUS_NO_SUCH_DOMAIN; } } if (dom_res == NULL && fill_on_blank_request) { /* blank inputs gives our domain - tested against w2k8r2. Without this ADUC on Win7 won't start */ domain_dn = ldb_get_default_basedn(sam_ctx); ret = ldb_search(sam_ctx, mem_ctx, &dom_res, domain_dn, LDB_SCOPE_BASE, dom_attrs, "objectClass=domain"); if (ret != LDB_SUCCESS) { DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", lpcfg_dnsdomain(lp_ctx), ldb_dn_get_linearized(domain_dn), ldb_errstring(sam_ctx))); return NT_STATUS_NO_SUCH_DOMAIN; } } if (dom_res == NULL) { DEBUG(2,(__location__ ": Unable to get domain information with no inputs\n")); return NT_STATUS_NO_SUCH_DOMAIN; } /* work around different inputs for not-specified users */ if (!user) { user = ""; } /* Enquire about any valid username with just a CLDAP packet - * if kerberos didn't also do this, the security folks would * scream... */ if (user[0]) { \ /* Only allow some bits to be enquired: [MS-ATDS] 7.3.3.2 */ if (acct_control == (uint32_t)-1) { acct_control = 0; } acct_control = acct_control & (ACB_TEMPDUP | ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST); /* We must exclude disabled accounts, but otherwise do the bitwise match the client asked for */ ret = ldb_search(sam_ctx, mem_ctx, &user_res, dom_res->msgs[0]->dn, LDB_SCOPE_SUBTREE, none_attrs, "(&(objectClass=user)(samAccountName=%s)" "(!(userAccountControl:" LDB_OID_COMPARATOR_AND ":=%u))" "(userAccountControl:" LDB_OID_COMPARATOR_OR ":=%u))", ldb_binary_encode_string(mem_ctx, user), UF_ACCOUNTDISABLE, ds_acb2uf(acct_control)); if (ret != LDB_SUCCESS) { DEBUG(2,("Unable to find reference to user '%s' with ACB 0x%8x under %s: %s\n", user, acct_control, ldb_dn_get_linearized(dom_res->msgs[0]->dn), ldb_errstring(sam_ctx))); return NT_STATUS_NO_SUCH_USER; } else if (user_res->count == 1) { user_known = true; } else { user_known = false; } } else { user_known = true; } server_type = DS_SERVER_DS | DS_SERVER_TIMESERV | DS_SERVER_GOOD_TIMESERV; if (samdb_is_pdc(sam_ctx)) { server_type |= DS_SERVER_PDC; } if (dsdb_functional_level(sam_ctx) >= DS_DOMAIN_FUNCTION_2008) { server_type |= DS_SERVER_FULL_SECRET_DOMAIN_6; } if (samdb_is_gc(sam_ctx)) { server_type |= DS_SERVER_GC; } if (str_list_check(services, "ldap")) { server_type |= DS_SERVER_LDAP; } if (str_list_check(services, "kdc")) { server_type |= DS_SERVER_KDC; } if (samdb_rodc(sam_ctx, &am_rodc) == LDB_SUCCESS && !am_rodc) { server_type |= DS_SERVER_WRITABLE; } pdc_name = talloc_asprintf(mem_ctx, "\\\\%s", lpcfg_netbios_name(lp_ctx)); NT_STATUS_HAVE_NO_MEMORY(pdc_name); domain_uuid = samdb_result_guid(dom_res->msgs[0], "objectGUID"); dns_domain = lpcfg_dnsdomain(lp_ctx); forest_domain = samdb_forest_name(sam_ctx, mem_ctx); NT_STATUS_HAVE_NO_MEMORY(forest_domain); pdc_dns_name = talloc_asprintf(mem_ctx, "%s.%s", strlower_talloc(mem_ctx, lpcfg_netbios_name(lp_ctx)), dns_domain); NT_STATUS_HAVE_NO_MEMORY(pdc_dns_name); flatname = lpcfg_workgroup(lp_ctx); server_site = samdb_server_site_name(sam_ctx, mem_ctx); NT_STATUS_HAVE_NO_MEMORY(server_site); client_site = samdb_client_site_name(sam_ctx, mem_ctx, src_address, NULL); NT_STATUS_HAVE_NO_MEMORY(client_site); if (strcasecmp(server_site, client_site) == 0) { server_type |= DS_SERVER_CLOSEST; } load_interface_list(mem_ctx, lp_ctx, &ifaces); if (src_address) { pdc_ip = iface_list_best_ip(ifaces, src_address); } else { pdc_ip = iface_list_first_v4(ifaces); } if (pdc_ip == NULL || !is_ipaddress_v4(pdc_ip)) { /* this matches windows behaviour */ pdc_ip = "127.0.0.1"; } ZERO_STRUCTP(netlogon); /* check if either of these bits is present */ if (version & (NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_5EX_WITH_IP)) { uint32_t extra_flags = 0; netlogon->ntver = NETLOGON_NT_VERSION_5EX; /* could check if the user exists */ if (user_known) { netlogon->data.nt5_ex.command = LOGON_SAM_LOGON_RESPONSE_EX; } else { netlogon->data.nt5_ex.command = LOGON_SAM_LOGON_USER_UNKNOWN_EX; } netlogon->data.nt5_ex.pdc_name = pdc_name; netlogon->data.nt5_ex.user_name = user; netlogon->data.nt5_ex.domain_name = flatname; netlogon->data.nt5_ex.domain_uuid = domain_uuid; netlogon->data.nt5_ex.forest = forest_domain; netlogon->data.nt5_ex.dns_domain = dns_domain; netlogon->data.nt5_ex.pdc_dns_name = pdc_dns_name; netlogon->data.nt5_ex.server_site = server_site; netlogon->data.nt5_ex.client_site = client_site; if (version & NETLOGON_NT_VERSION_5EX_WITH_IP) { /* note that this is always a IPV4 address */ extra_flags = NETLOGON_NT_VERSION_5EX_WITH_IP; netlogon->data.nt5_ex.sockaddr.sockaddr_family = 2; netlogon->data.nt5_ex.sockaddr.pdc_ip = pdc_ip; netlogon->data.nt5_ex.sockaddr.remaining = data_blob_talloc_zero(mem_ctx, 8); } netlogon->data.nt5_ex.server_type = server_type; netlogon->data.nt5_ex.nt_version = NETLOGON_NT_VERSION_1|NETLOGON_NT_VERSION_5EX|extra_flags; netlogon->data.nt5_ex.lmnt_token = 0xFFFF; netlogon->data.nt5_ex.lm20_token = 0xFFFF; } else if (version & NETLOGON_NT_VERSION_5) { netlogon->ntver = NETLOGON_NT_VERSION_5; /* could check if the user exists */ if (user_known) { netlogon->data.nt5.command = LOGON_SAM_LOGON_RESPONSE; } else { netlogon->data.nt5.command = LOGON_SAM_LOGON_USER_UNKNOWN; } netlogon->data.nt5.pdc_name = pdc_name; netlogon->data.nt5.user_name = user; netlogon->data.nt5.domain_name = flatname; netlogon->data.nt5.domain_uuid = domain_uuid; netlogon->data.nt5.forest = forest_domain; netlogon->data.nt5.dns_domain = dns_domain; netlogon->data.nt5.pdc_dns_name = pdc_dns_name; netlogon->data.nt5.pdc_ip = pdc_ip; netlogon->data.nt5.server_type = server_type; netlogon->data.nt5.nt_version = NETLOGON_NT_VERSION_1|NETLOGON_NT_VERSION_5; netlogon->data.nt5.lmnt_token = 0xFFFF; netlogon->data.nt5.lm20_token = 0xFFFF; } else /* (version & NETLOGON_NT_VERSION_1) and all other cases */ { netlogon->ntver = NETLOGON_NT_VERSION_1; /* could check if the user exists */ if (user_known) { netlogon->data.nt4.command = LOGON_SAM_LOGON_RESPONSE; } else { netlogon->data.nt4.command = LOGON_SAM_LOGON_USER_UNKNOWN; } netlogon->data.nt4.pdc_name = pdc_name; netlogon->data.nt4.user_name = user; netlogon->data.nt4.domain_name = flatname; netlogon->data.nt4.nt_version = NETLOGON_NT_VERSION_1; netlogon->data.nt4.lmnt_token = 0xFFFF; netlogon->data.nt4.lm20_token = 0xFFFF; } return NT_STATUS_OK; }
_PUBLIC_ struct test_join *torture_join_domain(struct torture_context *tctx, const char *machine_name, uint32_t acct_flags, struct cli_credentials **machine_credentials) { NTSTATUS status; struct libnet_context *libnet_ctx; struct libnet_JoinDomain *libnet_r; struct test_join *tj; struct samr_SetUserInfo s; union samr_UserInfo u; tj = talloc_zero(tctx, struct test_join); if (!tj) return NULL; libnet_r = talloc_zero(tj, struct libnet_JoinDomain); if (!libnet_r) { talloc_free(tj); return NULL; } libnet_ctx = libnet_context_init(tctx->ev, tctx->lp_ctx); if (!libnet_ctx) { talloc_free(tj); return NULL; } tj->libnet_r = libnet_r; libnet_ctx->cred = cmdline_credentials; libnet_r->in.binding = torture_setting_string(tctx, "binding", NULL); if (!libnet_r->in.binding) { libnet_r->in.binding = talloc_asprintf(libnet_r, "ncacn_np:%s", torture_setting_string(tctx, "host", NULL)); } libnet_r->in.level = LIBNET_JOINDOMAIN_SPECIFIED; libnet_r->in.netbios_name = machine_name; libnet_r->in.account_name = talloc_asprintf(libnet_r, "%s$", machine_name); if (!libnet_r->in.account_name) { talloc_free(tj); return NULL; } libnet_r->in.acct_type = acct_flags; libnet_r->in.recreate_account = true; status = libnet_JoinDomain(libnet_ctx, libnet_r, libnet_r); if (!NT_STATUS_IS_OK(status)) { if (libnet_r->out.error_string) { DEBUG(0, ("Domain join failed - %s\n", libnet_r->out.error_string)); } else { DEBUG(0, ("Domain join failed - %s\n", nt_errstr(status))); } talloc_free(tj); return NULL; } tj->p = libnet_r->out.samr_pipe; tj->user_handle = *libnet_r->out.user_handle; tj->dom_sid = libnet_r->out.domain_sid; talloc_steal(tj, libnet_r->out.domain_sid); tj->dom_netbios_name = libnet_r->out.domain_name; talloc_steal(tj, libnet_r->out.domain_name); tj->dom_dns_name = libnet_r->out.realm; talloc_steal(tj, libnet_r->out.realm); tj->user_guid = libnet_r->out.account_guid; tj->netbios_name = talloc_strdup(tj, machine_name); if (!tj->netbios_name) { talloc_free(tj); return NULL; } ZERO_STRUCT(u); s.in.user_handle = &tj->user_handle; s.in.info = &u; s.in.level = 21; u.info21.fields_present = SAMR_FIELD_DESCRIPTION | SAMR_FIELD_COMMENT | SAMR_FIELD_FULL_NAME; u.info21.comment.string = talloc_asprintf(tj, "Tortured by Samba4: %s", timestring(tj, time(NULL))); u.info21.full_name.string = talloc_asprintf(tj, "Torture account for Samba4: %s", timestring(tj, time(NULL))); u.info21.description.string = talloc_asprintf(tj, "Samba4 torture account created by host %s: %s", lpcfg_netbios_name(tctx->lp_ctx), timestring(tj, time(NULL))); status = dcerpc_samr_SetUserInfo_r(tj->p->binding_handle, tj, &s); if (!NT_STATUS_IS_OK(status)) { printf("SetUserInfo (non-critical) failed - %s\n", nt_errstr(status)); } if (!NT_STATUS_IS_OK(s.out.result)) { printf("SetUserInfo (non-critical) failed - %s\n", nt_errstr(s.out.result)); } *machine_credentials = cli_credentials_init(tj); cli_credentials_set_conf(*machine_credentials, tctx->lp_ctx); cli_credentials_set_workstation(*machine_credentials, machine_name, CRED_SPECIFIED); cli_credentials_set_domain(*machine_credentials, libnet_r->out.domain_name, CRED_SPECIFIED); if (libnet_r->out.realm) { cli_credentials_set_realm(*machine_credentials, libnet_r->out.realm, CRED_SPECIFIED); } cli_credentials_set_username(*machine_credentials, libnet_r->in.account_name, CRED_SPECIFIED); cli_credentials_set_password(*machine_credentials, libnet_r->out.join_password, CRED_SPECIFIED); cli_credentials_set_kvno(*machine_credentials, libnet_r->out.kvno); if (acct_flags & ACB_SVRTRUST) { cli_credentials_set_secure_channel_type(*machine_credentials, SEC_CHAN_BDC); } else if (acct_flags & ACB_WSTRUST) { cli_credentials_set_secure_channel_type(*machine_credentials, SEC_CHAN_WKSTA); } else { DEBUG(0, ("Invalid account type specificed to torture_join_domain\n")); talloc_free(*machine_credentials); return NULL; } return tj; }
struct test_join *torture_create_testuser_max_pwlen(struct torture_context *torture, const char *username, const char *domain, uint16_t acct_type, const char **random_password, int max_pw_len) { NTSTATUS status; struct samr_Connect c; struct samr_CreateUser2 r; struct samr_OpenDomain o; struct samr_LookupDomain l; struct dom_sid2 *sid = NULL; struct samr_GetUserPwInfo pwp; struct samr_PwInfo info; struct samr_SetUserInfo s; union samr_UserInfo u; struct policy_handle handle; uint32_t access_granted; uint32_t rid; DATA_BLOB session_key; struct lsa_String name; int policy_min_pw_len = 0; struct test_join *join; char *random_pw; const char *dc_binding = torture_setting_string(torture, "dc_binding", NULL); struct dcerpc_binding_handle *b = NULL; join = talloc(NULL, struct test_join); if (join == NULL) { return NULL; } ZERO_STRUCTP(join); printf("Connecting to SAMR\n"); if (dc_binding) { status = dcerpc_pipe_connect(join, &join->p, dc_binding, &ndr_table_samr, cmdline_credentials, NULL, torture->lp_ctx); } else { status = torture_rpc_connection(torture, &join->p, &ndr_table_samr); } if (!NT_STATUS_IS_OK(status)) { return NULL; } b = join->p->binding_handle; c.in.system_name = NULL; c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; c.out.connect_handle = &handle; status = dcerpc_samr_Connect_r(b, join, &c); if (!NT_STATUS_IS_OK(status)) { const char *errstr = nt_errstr(status); printf("samr_Connect failed - %s\n", errstr); return NULL; } if (!NT_STATUS_IS_OK(c.out.result)) { const char *errstr = nt_errstr(c.out.result); printf("samr_Connect failed - %s\n", errstr); return NULL; } if (domain) { printf("Opening domain %s\n", domain); name.string = domain; l.in.connect_handle = &handle; l.in.domain_name = &name; l.out.sid = &sid; status = dcerpc_samr_LookupDomain_r(b, join, &l); if (!NT_STATUS_IS_OK(status)) { printf("LookupDomain failed - %s\n", nt_errstr(status)); goto failed; } if (!NT_STATUS_IS_OK(l.out.result)) { printf("LookupDomain failed - %s\n", nt_errstr(l.out.result)); goto failed; } } else { struct samr_EnumDomains e; uint32_t resume_handle = 0, num_entries; struct samr_SamArray *sam; int i; e.in.connect_handle = &handle; e.in.buf_size = (uint32_t)-1; e.in.resume_handle = &resume_handle; e.out.sam = &sam; e.out.num_entries = &num_entries; e.out.resume_handle = &resume_handle; status = dcerpc_samr_EnumDomains_r(b, join, &e); if (!NT_STATUS_IS_OK(status)) { printf("EnumDomains failed - %s\n", nt_errstr(status)); goto failed; } if (!NT_STATUS_IS_OK(e.out.result)) { printf("EnumDomains failed - %s\n", nt_errstr(e.out.result)); goto failed; } if ((num_entries != 2) || (sam && sam->count != 2)) { printf("unexpected number of domains\n"); goto failed; } for (i=0; i < 2; i++) { if (!strequal(sam->entries[i].name.string, "builtin")) { domain = sam->entries[i].name.string; break; } } if (domain) { printf("Opening domain %s\n", domain); name.string = domain; l.in.connect_handle = &handle; l.in.domain_name = &name; l.out.sid = &sid; status = dcerpc_samr_LookupDomain_r(b, join, &l); if (!NT_STATUS_IS_OK(status)) { printf("LookupDomain failed - %s\n", nt_errstr(status)); goto failed; } if (!NT_STATUS_IS_OK(l.out.result)) { printf("LookupDomain failed - %s\n", nt_errstr(l.out.result)); goto failed; } } else { printf("cannot proceed without domain name\n"); goto failed; } } talloc_steal(join, *l.out.sid); join->dom_sid = *l.out.sid; join->dom_netbios_name = talloc_strdup(join, domain); if (!join->dom_netbios_name) goto failed; o.in.connect_handle = &handle; o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; o.in.sid = *l.out.sid; o.out.domain_handle = &join->domain_handle; status = dcerpc_samr_OpenDomain_r(b, join, &o); if (!NT_STATUS_IS_OK(status)) { printf("OpenDomain failed - %s\n", nt_errstr(status)); goto failed; } if (!NT_STATUS_IS_OK(o.out.result)) { printf("OpenDomain failed - %s\n", nt_errstr(o.out.result)); goto failed; } printf("Creating account %s\n", username); again: name.string = username; r.in.domain_handle = &join->domain_handle; r.in.account_name = &name; r.in.acct_flags = acct_type; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.out.user_handle = &join->user_handle; r.out.access_granted = &access_granted; r.out.rid = &rid; status = dcerpc_samr_CreateUser2_r(b, join, &r); if (!NT_STATUS_IS_OK(status)) { printf("CreateUser2 failed - %s\n", nt_errstr(status)); goto failed; } if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) { status = DeleteUser_byname(b, join, &join->domain_handle, name.string); if (NT_STATUS_IS_OK(status)) { goto again; } } if (!NT_STATUS_IS_OK(r.out.result)) { printf("CreateUser2 failed - %s\n", nt_errstr(r.out.result)); goto failed; } join->user_sid = dom_sid_add_rid(join, join->dom_sid, rid); pwp.in.user_handle = &join->user_handle; pwp.out.info = &info; status = dcerpc_samr_GetUserPwInfo_r(b, join, &pwp); if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(pwp.out.result)) { policy_min_pw_len = pwp.out.info->min_password_length; } random_pw = generate_random_password(join, MAX(8, policy_min_pw_len), max_pw_len); printf("Setting account password '%s'\n", random_pw); ZERO_STRUCT(u); s.in.user_handle = &join->user_handle; s.in.info = &u; s.in.level = 24; encode_pw_buffer(u.info24.password.data, random_pw, STR_UNICODE); u.info24.password_expired = 0; status = dcerpc_fetch_session_key(join->p, &session_key); if (!NT_STATUS_IS_OK(status)) { printf("SetUserInfo level %u - no session key - %s\n", s.in.level, nt_errstr(status)); torture_leave_domain(torture, join); goto failed; } arcfour_crypt_blob(u.info24.password.data, 516, &session_key); status = dcerpc_samr_SetUserInfo_r(b, join, &s); if (!NT_STATUS_IS_OK(status)) { printf("SetUserInfo failed - %s\n", nt_errstr(status)); goto failed; } if (!NT_STATUS_IS_OK(s.out.result)) { printf("SetUserInfo failed - %s\n", nt_errstr(s.out.result)); goto failed; } ZERO_STRUCT(u); s.in.user_handle = &join->user_handle; s.in.info = &u; s.in.level = 21; u.info21.acct_flags = acct_type | ACB_PWNOEXP; u.info21.fields_present = SAMR_FIELD_ACCT_FLAGS | SAMR_FIELD_DESCRIPTION | SAMR_FIELD_COMMENT | SAMR_FIELD_FULL_NAME; u.info21.comment.string = talloc_asprintf(join, "Tortured by Samba4: %s", timestring(join, time(NULL))); u.info21.full_name.string = talloc_asprintf(join, "Torture account for Samba4: %s", timestring(join, time(NULL))); u.info21.description.string = talloc_asprintf(join, "Samba4 torture account created by host %s: %s", lpcfg_netbios_name(torture->lp_ctx), timestring(join, time(NULL))); printf("Resetting ACB flags, force pw change time\n"); status = dcerpc_samr_SetUserInfo_r(b, join, &s); if (!NT_STATUS_IS_OK(status)) { printf("SetUserInfo failed - %s\n", nt_errstr(status)); goto failed; } if (!NT_STATUS_IS_OK(s.out.result)) { printf("SetUserInfo failed - %s\n", nt_errstr(s.out.result)); goto failed; } if (random_password) { *random_password = random_pw; } return join; failed: torture_leave_domain(torture, join); return NULL; }
struct dnsserver_serverinfo *dnsserver_init_serverinfo(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, struct ldb_context *samdb) { struct dnsserver_serverinfo *serverinfo; struct dcerpc_server_info *dinfo; struct ldb_dn *domain_dn, *forest_dn; struct interface *ifaces; int num_interfaces, i; serverinfo = talloc_zero(mem_ctx, struct dnsserver_serverinfo); if (serverinfo == NULL) { return NULL; } dinfo = lpcfg_dcerpc_server_info(mem_ctx, lp_ctx); if (dinfo) { serverinfo->dwVersion = (dinfo->version_build & 0x0000FFFF) << 16 | (dinfo->version_minor & 0x000000FF) << 8 | (dinfo->version_major & 0x000000FF); talloc_free(dinfo); } else { serverinfo->dwVersion = 0x0ECE0205; /* build, os_minor, os_major */; } serverinfo->fBootMethod = DNS_BOOT_METHOD_DIRECTORY; serverinfo->fAdminConfigured = 0; serverinfo->fAllowUpdate = 1; serverinfo->fDsAvailable = 1; serverinfo->pszServerName = talloc_asprintf(mem_ctx, "%s.%s", lpcfg_netbios_name(lp_ctx), lpcfg_dnsdomain(lp_ctx)); domain_dn = ldb_get_default_basedn(samdb); forest_dn = ldb_get_root_basedn(samdb); serverinfo->pszDsContainer = talloc_asprintf(mem_ctx, "CN=MicrosoftDNS,DC=DomainDnsZones,%s", ldb_dn_get_linearized(domain_dn)); serverinfo->dwDsForestVersion = dsdb_forest_functional_level(samdb); serverinfo->dwDsDomainVersion = dsdb_functional_level(samdb); serverinfo->dwDsDsaVersion = 4; /* need to do ldb search here */ serverinfo->pszDomainName = samdb_dn_to_dns_domain(mem_ctx, domain_dn); serverinfo->pszForestName = samdb_dn_to_dns_domain(mem_ctx, forest_dn); serverinfo->pszDomainDirectoryPartition = talloc_asprintf(mem_ctx, "DC=DomainDnsZones,%s", ldb_dn_get_linearized(domain_dn)); serverinfo->pszForestDirectoryPartition = talloc_asprintf(mem_ctx, "DC=ForestDnsZones,%s", ldb_dn_get_linearized(forest_dn)); load_interface_list(mem_ctx, lp_ctx, &ifaces); num_interfaces = iface_list_count(ifaces); serverinfo->aipServerAddrs = talloc_zero(mem_ctx, struct IP4_ARRAY); if (serverinfo->aipServerAddrs) { serverinfo->aipServerAddrs->AddrCount = num_interfaces; if (num_interfaces > 0) { serverinfo->aipServerAddrs->AddrArray = talloc_zero_array(mem_ctx, unsigned int, num_interfaces); if (serverinfo->aipServerAddrs->AddrArray) { for (i=0; i<num_interfaces; i++) { serverinfo->aipServerAddrs->AddrArray[i] = inet_addr(iface_list_n_ip(ifaces, i)); } } else { serverinfo->aipServerAddrs->AddrCount = 0; } }
static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, struct auth_user_info_dc **user_info_dc) { NTSTATUS nt_status; const char *account_name = user_info->mapped.account_name; struct ldb_message *msg; struct ldb_dn *domain_dn; DATA_BLOB user_sess_key, lm_sess_key; TALLOC_CTX *tmp_ctx; if (ctx->auth_ctx->sam_ctx == NULL) { DEBUG(0, ("No SAM available, cannot log in users\n")); return NT_STATUS_INVALID_SYSTEM_SERVICE; } if (!account_name || !*account_name) { /* 'not for me' */ return NT_STATUS_NOT_IMPLEMENTED; } tmp_ctx = talloc_new(mem_ctx); if (!tmp_ctx) { return NT_STATUS_NO_MEMORY; } domain_dn = ldb_get_default_basedn(ctx->auth_ctx->sam_ctx); if (domain_dn == NULL) { talloc_free(tmp_ctx); return NT_STATUS_NO_SUCH_DOMAIN; } nt_status = authsam_search_account(tmp_ctx, ctx->auth_ctx->sam_ctx, account_name, domain_dn, &msg); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(tmp_ctx); return nt_status; } nt_status = authsam_authenticate(ctx->auth_ctx, tmp_ctx, ctx->auth_ctx->sam_ctx, domain_dn, msg, user_info, &user_sess_key, &lm_sess_key); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(tmp_ctx); return nt_status; } nt_status = authsam_make_user_info_dc(tmp_ctx, ctx->auth_ctx->sam_ctx, lpcfg_netbios_name(ctx->auth_ctx->lp_ctx), lpcfg_sam_name(ctx->auth_ctx->lp_ctx), domain_dn, msg, user_sess_key, lm_sess_key, user_info_dc); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(tmp_ctx); return nt_status; } talloc_steal(mem_ctx, *user_info_dc); talloc_free(tmp_ctx); return NT_STATUS_OK; }