static NTSTATUS smb2srv_negprot_secblob(struct smb2srv_request *req, DATA_BLOB *_blob) { struct gensec_security *gensec_security; DATA_BLOB null_data_blob = data_blob(NULL, 0); DATA_BLOB blob; NTSTATUS nt_status; struct cli_credentials *server_credentials; server_credentials = cli_credentials_init(req); if (!server_credentials) { smbsrv_terminate_connection(req->smb_conn, "Failed to init server credentials\n"); return NT_STATUS_NO_MEMORY; } cli_credentials_set_conf(server_credentials, req->smb_conn->lp_ctx); nt_status = cli_credentials_set_machine_account(server_credentials, req->smb_conn->lp_ctx); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(10, ("Failed to obtain server credentials, perhaps a standalone server?: %s\n", nt_errstr(nt_status))); /* * We keep the server_credentials as anonymous * this is required for the spoolss.notify test */ } req->smb_conn->negotiate.server_credentials = talloc_steal(req->smb_conn, server_credentials); nt_status = samba_server_gensec_start(req, req->smb_conn->connection->event.ctx, req->smb_conn->connection->msg_ctx, req->smb_conn->lp_ctx, server_credentials, "cifs", &gensec_security); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("Failed to start GENSEC: %s\n", nt_errstr(nt_status))); smbsrv_terminate_connection(req->smb_conn, "Failed to start GENSEC\n"); return nt_status; } gensec_set_target_service(gensec_security, "cifs"); gensec_set_credentials(gensec_security, server_credentials); nt_status = gensec_start_mech_by_oid(gensec_security, GENSEC_OID_SPNEGO); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("Failed to start SPNEGO: %s\n", nt_errstr(nt_status))); smbsrv_terminate_connection(req->smb_conn, "Failed to start SPNEGO\n"); return nt_status; } nt_status = gensec_update_ev(gensec_security, req, req->smb_conn->connection->event.ctx, null_data_blob, &blob); if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { DEBUG(0, ("Failed to get SPNEGO to give us the first token: %s\n", nt_errstr(nt_status))); smbsrv_terminate_connection(req->smb_conn, "Failed to start SPNEGO - no first token\n"); return nt_status; } *_blob = blob; return NT_STATUS_OK; }
static bool try_failed_login(struct torture_context *tctx, struct smbcli_state *cli) { NTSTATUS status; struct smb_composite_sesssetup setup; struct smbcli_session *session; struct smbcli_session_options options; lpcfg_smbcli_session_options(tctx->lp_ctx, &options); session = smbcli_session_init(cli->transport, cli, false, options); setup.in.sesskey = cli->transport->negotiate.sesskey; setup.in.capabilities = cli->transport->negotiate.capabilities; setup.in.workgroup = lpcfg_workgroup(tctx->lp_ctx); setup.in.credentials = cli_credentials_init(session); setup.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx); cli_credentials_set_conf(setup.in.credentials, tctx->lp_ctx); cli_credentials_set_domain(setup.in.credentials, "INVALID-DOMAIN", CRED_SPECIFIED); cli_credentials_set_username(setup.in.credentials, "INVALID-USERNAME", CRED_SPECIFIED); cli_credentials_set_password(setup.in.credentials, "INVALID-PASSWORD", CRED_SPECIFIED); status = smb_composite_sesssetup(session, &setup); talloc_free(session); if (NT_STATUS_IS_OK(status)) { printf("Allowed session setup with invalid credentials?!\n"); return false; } return true; }
NTSTATUS wbsrv_samba3_pam_auth(struct wbsrv_samba3_call *s3call) { struct composite_context *ctx; struct wbsrv_service *service = s3call->wbconn->listen_socket->service; struct cli_credentials *credentials; char *user, *domain; if (!wb_samba3_split_username(s3call, s3call->wbconn->lp_ctx, s3call->request.data.auth.user, &domain, &user)) { return NT_STATUS_NO_SUCH_USER; } credentials = cli_credentials_init(s3call); if (!credentials) { return NT_STATUS_NO_MEMORY; } cli_credentials_set_conf(credentials, service->task->lp_ctx); cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED); cli_credentials_set_username(credentials, user, CRED_SPECIFIED); cli_credentials_set_password(credentials, s3call->request.data.auth.pass, CRED_SPECIFIED); ctx = wb_cmd_pam_auth_send(s3call, service, credentials); NT_STATUS_HAVE_NO_MEMORY(ctx); ctx->async.fn = pam_auth_recv; ctx->async.private_data = s3call; s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC; return NT_STATUS_OK; }
NTSTATUS wbsrv_samba3_check_machacc(struct wbsrv_samba3_call *s3call) { NTSTATUS status; struct cli_credentials *creds; struct composite_context *ctx; struct wbsrv_service *service = s3call->wbconn->listen_socket->service; /* Create a credentials structure */ creds = cli_credentials_init(s3call); if (creds == NULL) { return NT_STATUS_NO_MEMORY; } cli_credentials_set_conf(creds, service->task->lp_ctx); /* Connect the machine account to the credentials */ status = cli_credentials_set_machine_account(creds, service->task->lp_ctx); if (!NT_STATUS_IS_OK(status)) { talloc_free(creds); return status; } ctx = wb_cmd_pam_auth_send(s3call, service, creds); if (!ctx) { talloc_free(creds); return NT_STATUS_NO_MEMORY; } ctx->async.fn = check_machacc_recv; ctx->async.private_data = s3call; s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC; return NT_STATUS_OK; }
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; }
/* parse any auth information from a dcerpc bind request return false if we can't handle the auth request for some reason (in which case we send a bind_nak) */ bool dcesrv_auth_bind(struct dcesrv_call_state *call) { struct cli_credentials *server_credentials; struct ncacn_packet *pkt = &call->pkt; struct dcesrv_connection *dce_conn = call->conn; struct dcesrv_auth *auth = &dce_conn->auth_state; NTSTATUS status; uint32_t auth_length; if (pkt->u.bind.auth_info.length == 0) { dce_conn->auth_state.auth_info = NULL; return true; } dce_conn->auth_state.auth_info = talloc(dce_conn, struct dcerpc_auth); if (!dce_conn->auth_state.auth_info) { return false; } status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.bind.auth_info, dce_conn->auth_state.auth_info, &auth_length, false); server_credentials = cli_credentials_init(call); if (!server_credentials) { DEBUG(1, ("Failed to init server credentials\n")); return false; } cli_credentials_set_conf(server_credentials, call->conn->dce_ctx->lp_ctx); status = cli_credentials_set_machine_account(server_credentials, call->conn->dce_ctx->lp_ctx); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Failed to obtain server credentials, perhaps a standalone server?: %s\n", nt_errstr(status))); talloc_free(server_credentials); server_credentials = NULL; } status = samba_server_gensec_start(dce_conn, call->event_ctx, call->msg_ctx, call->conn->dce_ctx->lp_ctx, server_credentials, NULL, &auth->gensec_security); status = gensec_start_mech_by_authtype(auth->gensec_security, auth->auth_info->auth_type, auth->auth_info->auth_level); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("Failed to start GENSEC mechanism for DCERPC server: auth_type=%d, auth_level=%d: %s\n", (int)auth->auth_info->auth_type, (int)auth->auth_info->auth_level, nt_errstr(status))); return false; } return true; }
/** * Create a new anonymous credential * @param mem_ctx TALLOC_CTX parent for credentials structure */ _PUBLIC_ struct cli_credentials *cli_credentials_init_anon(TALLOC_CTX *mem_ctx) { struct cli_credentials *anon_credentials; anon_credentials = cli_credentials_init(mem_ctx); cli_credentials_set_anonymous(anon_credentials); return anon_credentials; }
static int ejs_net_context(MprVarHandle eid, int argc, struct MprVar **argv) { TALLOC_CTX *event_mem_ctx = talloc_new(mprMemCtx()); struct cli_credentials *creds; struct libnet_context *ctx; struct MprVar obj; struct event_context *ev; if (!event_mem_ctx) { ejsSetErrorMsg(eid, "talloc_new() failed"); return -1; } ev = event_context_find(event_mem_ctx); ctx = libnet_context_init(ev); /* IF we generated a new event context, it will be under here, * and we need it to last as long as the libnet context, so * make it a child */ talloc_steal(ctx, event_mem_ctx); if (argc == 0 || (argc == 1 && argv[0]->type == MPR_TYPE_NULL)) { creds = cli_credentials_init(ctx); if (creds == NULL) { ejsSetErrorMsg(eid, "cli_credential_init() failed"); talloc_free(ctx); return -1; } cli_credentials_set_conf(creds); cli_credentials_set_anonymous(creds); } else if (argc == 1 && argv[0]->type == MPR_TYPE_OBJECT) { /* get credential values from credentials object */ creds = mprGetPtr(argv[0], "creds"); if (creds == NULL) { ejsSetErrorMsg(eid, "userAuth requires a 'creds' first parameter"); talloc_free(ctx); return -1; } } else { ejsSetErrorMsg(eid, "NetContext invalid arguments, this function requires an object."); talloc_free(ctx); return -1; } ctx->cred = creds; obj = mprObject("NetCtx"); mprSetPtrChild(&obj, "ctx", ctx); mprSetCFunction(&obj, "UserMgr", ejs_net_userman); mprSetCFunction(&obj, "JoinDomain", ejs_net_join_domain); mprSetCFunction(&obj, "SamSyncLdb", ejs_net_samsync_ldb); mpr_Return(eid, obj); return 0; }
static int ejs_tree_connect(MprVarHandle eid, int argc, char **argv) { struct cli_credentials *creds; struct smb_composite_connect io; struct smbcli_tree *tree; char *hostname, *sharename; NTSTATUS result; TALLOC_CTX *mem_ctx; if (argc != 2) { ejsSetErrorMsg(eid, "tree_connect(): invalid number of args"); return -1; } /* Set up host, share destination */ mem_ctx = talloc_new(mprMemCtx()); smbcli_parse_unc(argv[0], mem_ctx, &hostname, &sharename); /* Set up credentials */ creds = cli_credentials_init(NULL); cli_credentials_set_conf(creds); cli_credentials_parse_string(creds, argv[1], CRED_SPECIFIED); /* Do connect */ io.in.dest_host = hostname; io.in.port = 0; io.in.called_name = strupper_talloc(mem_ctx, hostname); io.in.service = sharename; io.in.service_type = "?????"; io.in.credentials = creds; io.in.fallback_to_anonymous = False; io.in.workgroup = lp_workgroup(); result = smb_composite_connect(&io, mem_ctx, NULL); tree = io.out.tree; talloc_free(mem_ctx); if (!NT_STATUS_IS_OK(result)) { mpr_Return(eid, mprNTSTATUS(result)); return 0; } mpr_Return(eid, mprCreatePtrVar(tree)); return 0; }
NTSTATUS auth_ntlmssp_client_prepare(TALLOC_CTX *mem_ctx, struct auth_generic_state **auth_ntlmssp_state) { struct auth_generic_state *ans; NTSTATUS nt_status; struct gensec_settings *gensec_settings; struct loadparm_context *lp_ctx; ans = talloc_zero(mem_ctx, struct auth_generic_state); if (!ans) { DEBUG(0,("auth_ntlmssp_start: talloc failed!\n")); return NT_STATUS_NO_MEMORY; } lp_ctx = loadparm_init_s3(ans, loadparm_s3_context()); if (lp_ctx == NULL) { DEBUG(10, ("loadparm_init_s3 failed\n")); TALLOC_FREE(ans); return NT_STATUS_INVALID_SERVER_STATE; } gensec_settings = lpcfg_gensec_settings(ans, lp_ctx); if (lp_ctx == NULL) { DEBUG(10, ("lpcfg_gensec_settings failed\n")); TALLOC_FREE(ans); return NT_STATUS_NO_MEMORY; } nt_status = gensec_client_start(ans, &ans->gensec_security, gensec_settings); if (!NT_STATUS_IS_OK(nt_status)) { TALLOC_FREE(ans); return nt_status; } ans->credentials = cli_credentials_init(ans); if (!ans->credentials) { TALLOC_FREE(ans); return NT_STATUS_NO_MEMORY; } cli_credentials_guess(ans->credentials, lp_ctx); talloc_unlink(ans, lp_ctx); talloc_unlink(ans, gensec_settings); *auth_ntlmssp_state = ans; return NT_STATUS_OK; }
static PyObject *py_creds_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { pytalloc_Object *ret = (pytalloc_Object *)type->tp_alloc(type, 0); if (ret == NULL) { PyErr_NoMemory(); return NULL; } ret->talloc_ctx = talloc_new(NULL); if (ret->talloc_ctx == NULL) { PyErr_NoMemory(); return NULL; } ret->ptr = cli_credentials_init(ret->talloc_ctx); return (PyObject *)ret; }
/** * Connect to a specific interface, but ask the user * for information not specified */ struct dcerpc_binding_handle *gtk_connect_rpc_interface(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx, struct loadparm_context *lp_ctx, const struct ndr_interface_table *table) { GtkRpcBindingDialog *d; NTSTATUS status; struct dcerpc_binding_handle *pipe; struct cli_credentials *cred; gint result; d = SAMBAGTK_RPC_BINDING_DIALOG(gtk_rpc_binding_dialog_new(NULL)); result = gtk_dialog_run(GTK_DIALOG(d)); if (result != GTK_RESPONSE_ACCEPT) { gtk_widget_destroy(GTK_WIDGET(d)); return NULL; } cred = cli_credentials_init(mem_ctx); cli_credentials_guess(cred, lp_ctx); cli_credentials_set_gtk_callbacks(cred); status = dcerpc_pipe_connect_b(mem_ctx, &pipe, gtk_rpc_binding_dialog_get_binding(d, mem_ctx), table, cred, ev_ctx, lp_ctx); if(!NT_STATUS_IS_OK(status)) { gtk_show_ntstatus(NULL, "While connecting to interface", status); gtk_widget_destroy(GTK_WIDGET(d)); talloc_free(cred); return NULL; } gtk_widget_destroy(GTK_WIDGET(d)); talloc_free(cred); return pipe; }
static bool test_init(struct torture_context *tctx) { struct cli_credentials *creds = cli_credentials_init(tctx); cli_credentials_set_domain(creds, "bla", CRED_SPECIFIED); torture_assert_str_equal(tctx, "BLA", cli_credentials_get_domain(creds), "domain"); cli_credentials_set_username(creds, "someuser", CRED_SPECIFIED); torture_assert_str_equal(tctx, "someuser", cli_credentials_get_username(creds), "username"); cli_credentials_set_password(creds, "p4ssw0rd", CRED_SPECIFIED); torture_assert_str_equal(tctx, "p4ssw0rd", cli_credentials_get_password(creds), "password"); return true; }
_PUBLIC_ NTSTATUS auth_anonymous_session_info(TALLOC_CTX *parent_ctx, struct tevent_context *event_ctx, struct loadparm_context *lp_ctx, struct auth_session_info **_session_info) { NTSTATUS nt_status; struct auth_serversupplied_info *server_info = NULL; struct auth_session_info *session_info = NULL; TALLOC_CTX *mem_ctx = talloc_new(parent_ctx); nt_status = auth_anonymous_server_info(mem_ctx, lp_netbios_name(lp_ctx), &server_info); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); return nt_status; } /* references the server_info into the session_info */ nt_status = auth_generate_session_info(parent_ctx, event_ctx, lp_ctx, server_info, &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_anonymous(session_info->credentials); *_session_info = session_info; return NT_STATUS_OK; }
/* 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; }
NTSTATUS auth_generic_client_prepare(TALLOC_CTX *mem_ctx, struct auth_generic_state **auth_generic_state) { struct auth_generic_state *ans; NTSTATUS nt_status; size_t idx = 0; struct gensec_settings *gensec_settings; struct loadparm_context *lp_ctx; ans = talloc_zero(mem_ctx, struct auth_generic_state); if (!ans) { DEBUG(0,("auth_generic_start: talloc failed!\n")); return NT_STATUS_NO_MEMORY; } lp_ctx = loadparm_init_s3(ans, loadparm_s3_context()); if (lp_ctx == NULL) { DEBUG(10, ("loadparm_init_s3 failed\n")); TALLOC_FREE(ans); return NT_STATUS_INVALID_SERVER_STATE; } gensec_settings = lpcfg_gensec_settings(ans, lp_ctx); if (lp_ctx == NULL) { DEBUG(10, ("lpcfg_gensec_settings failed\n")); TALLOC_FREE(ans); return NT_STATUS_NO_MEMORY; } gensec_settings->backends = talloc_zero_array(gensec_settings, struct gensec_security_ops *, 4); if (gensec_settings->backends == NULL) { TALLOC_FREE(ans); return NT_STATUS_NO_MEMORY; } gensec_settings->backends[idx++] = &gensec_ntlmssp3_client_ops; #if defined(HAVE_KRB5) && defined(HAVE_GSS_WRAP_IOV) gensec_settings->backends[idx++] = &gensec_gse_krb5_security_ops; #endif gensec_init(); gensec_settings->backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_SPNEGO); nt_status = gensec_client_start(ans, &ans->gensec_security, gensec_settings); if (!NT_STATUS_IS_OK(nt_status)) { TALLOC_FREE(ans); return nt_status; } ans->credentials = cli_credentials_init(ans); if (!ans->credentials) { TALLOC_FREE(ans); return NT_STATUS_NO_MEMORY; } cli_credentials_guess(ans->credentials, lp_ctx); talloc_unlink(ans, lp_ctx); talloc_unlink(ans, gensec_settings); *auth_generic_state = ans; return NT_STATUS_OK; }
/* test session ops */ static BOOL test_session(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) { NTSTATUS status; BOOL ret = True; struct smbcli_session *session; struct smbcli_session *session2; struct smbcli_session *session3; struct smbcli_session *session4; struct cli_credentials *anon_creds; struct smbcli_session *sessions[15]; struct composite_context *composite_contexts[15]; struct smbcli_tree *tree; struct smb_composite_sesssetup setup; struct smb_composite_sesssetup setups[15]; union smb_open io; union smb_write wr; union smb_close cl; int fnum; const char *fname = BASEDIR "\\test.txt"; uint8_t c = 1; int i; printf("TESTING SESSION HANDLING\n"); if (!torture_setup_dir(cli, BASEDIR)) { return False; } printf("create a second security context on the same transport\n"); session = smbcli_session_init(cli->transport, mem_ctx, False); setup.in.sesskey = cli->transport->negotiate.sesskey; setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */ setup.in.workgroup = lp_workgroup(); setup.in.credentials = cmdline_credentials; status = smb_composite_sesssetup(session, &setup); CHECK_STATUS(status, NT_STATUS_OK); session->vuid = setup.out.vuid; printf("create a third security context on the same transport, with vuid set\n"); session2 = smbcli_session_init(cli->transport, mem_ctx, False); session2->vuid = session->vuid; setup.in.sesskey = cli->transport->negotiate.sesskey; setup.in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */ setup.in.workgroup = lp_workgroup(); setup.in.credentials = cmdline_credentials; status = smb_composite_sesssetup(session2, &setup); CHECK_STATUS(status, NT_STATUS_OK); session2->vuid = setup.out.vuid; printf("vuid1=%d vuid2=%d vuid3=%d\n", cli->session->vuid, session->vuid, session2->vuid); if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) { /* Samba4 currently fails this - we need to determine if this insane behaviour is important */ if (session2->vuid == session->vuid) { printf("server allows the user to re-use an existing vuid in session setup \n"); } } else { CHECK_NOT_VALUE(session2->vuid, session->vuid); } talloc_free(session2); if (cli->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) { printf("create a fourth security context on the same transport, without extended security\n"); session3 = smbcli_session_init(cli->transport, mem_ctx, False); session3->vuid = session->vuid; setup.in.sesskey = cli->transport->negotiate.sesskey; setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; /* force a non extended security login (should fail) */ setup.in.workgroup = lp_workgroup(); setup.in.credentials = cmdline_credentials; status = smb_composite_sesssetup(session3, &setup); CHECK_STATUS(status, NT_STATUS_LOGON_FAILURE); printf("create a fouth anonymous security context on the same transport, without extended security\n"); session4 = smbcli_session_init(cli->transport, mem_ctx, False); session4->vuid = session->vuid; setup.in.sesskey = cli->transport->negotiate.sesskey; setup.in.capabilities &= ~CAP_EXTENDED_SECURITY; /* force a non extended security login (should fail) */ setup.in.workgroup = lp_workgroup(); anon_creds = cli_credentials_init(mem_ctx); cli_credentials_set_conf(anon_creds); cli_credentials_set_anonymous(anon_creds); setup.in.credentials = anon_creds; status = smb_composite_sesssetup(session3, &setup); CHECK_STATUS(status, NT_STATUS_OK); talloc_free(session4); } printf("use the same tree as the existing connection\n"); tree = smbcli_tree_init(session, mem_ctx, False); tree->tid = cli->tree->tid; printf("create a file using the new vuid\n"); io.generic.level = RAW_OPEN_NTCREATEX; io.ntcreatex.in.root_fid = 0; io.ntcreatex.in.flags = 0; io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; io.ntcreatex.in.create_options = 0; io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; io.ntcreatex.in.alloc_size = 0; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE; io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname; status = smb_raw_open(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); fnum = io.ntcreatex.out.file.fnum; printf("write using the old vuid\n"); wr.generic.level = RAW_WRITE_WRITEX; wr.writex.in.file.fnum = fnum; wr.writex.in.offset = 0; wr.writex.in.wmode = 0; wr.writex.in.remaining = 0; wr.writex.in.count = 1; wr.writex.in.data = &c; status = smb_raw_write(cli->tree, &wr); CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE); printf("write with the new vuid\n"); status = smb_raw_write(tree, &wr); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(wr.writex.out.nwritten, 1); printf("logoff the new vuid\n"); status = smb_raw_ulogoff(session); CHECK_STATUS(status, NT_STATUS_OK); printf("the new vuid should not now be accessible\n"); status = smb_raw_write(tree, &wr); CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE); printf("second logoff for the new vuid should fail\n"); status = smb_raw_ulogoff(session); CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV, ERRbaduid)); talloc_free(session); printf("the fnum should have been auto-closed\n"); cl.close.level = RAW_CLOSE_CLOSE; cl.close.in.file.fnum = fnum; cl.close.in.write_time = 0; status = smb_raw_close(cli->tree, &cl); CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE); printf("create %d secondary security contexts on the same transport\n", (int)ARRAY_SIZE(sessions)); for (i=0; i <ARRAY_SIZE(sessions); i++) { setups[i].in.sesskey = cli->transport->negotiate.sesskey; setups[i].in.capabilities = cli->transport->negotiate.capabilities; /* ignored in secondary session setup, except by our libs, which care about the extended security bit */ setups[i].in.workgroup = lp_workgroup(); setups[i].in.credentials = cmdline_credentials; sessions[i] = smbcli_session_init(cli->transport, mem_ctx, False); composite_contexts[i] = smb_composite_sesssetup_send(sessions[i], &setups[i]); } /* flush the queue */ for (i=0; i < ARRAY_SIZE(sessions); i++) { event_loop_once(composite_contexts[0]->event_ctx); } printf("finishing %d secondary security contexts on the same transport\n", (int)ARRAY_SIZE(sessions)); for (i=0; i< ARRAY_SIZE(sessions); i++) { status = smb_composite_sesssetup_recv(composite_contexts[i]); CHECK_STATUS(status, NT_STATUS_OK); sessions[i]->vuid = setups[i].out.vuid; printf("VUID: %d\n", sessions[i]->vuid); status = smb_raw_ulogoff(sessions[i]); CHECK_STATUS(status, NT_STATUS_OK); } talloc_free(tree); done: return ret; }
_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(tctx, struct test_join); if (!tj) return NULL; libnet_r = talloc(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", lp_netbios_name(tctx->lp_ctx), timestring(tj, time(NULL))); status = dcerpc_samr_SetUserInfo(tj->p, tj, &s); if (!NT_STATUS_IS_OK(status)) { printf("SetUserInfo (non-critical) failed - %s\n", nt_errstr(status)); } *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; }
/* Fill out the auth_session_info with a cli_credentials based on the * auth_session_info we were forwarded over named pipe forwarding. * * NOTE: The stucture members of session_info_transport are stolen * with talloc_move() into auth_session_info for long term use */ struct auth_session_info *auth_session_info_from_transport(TALLOC_CTX *mem_ctx, struct auth_session_info_transport *session_info_transport, struct loadparm_context *lp_ctx, const char **reason) { struct auth_session_info *session_info; session_info = talloc_steal(mem_ctx, session_info_transport->session_info); if (session_info_transport->exported_gssapi_credentials.length) { struct cli_credentials *creds; OM_uint32 minor_status; gss_buffer_desc cred_token; gss_cred_id_t cred_handle; const char *error_string; int ret; DEBUG(10, ("Delegated credentials supplied by client\n")); cred_token.value = session_info_transport->exported_gssapi_credentials.data; cred_token.length = session_info_transport->exported_gssapi_credentials.length; ret = gss_import_cred(&minor_status, &cred_token, &cred_handle); if (ret != GSS_S_COMPLETE) { *reason = "Internal error in gss_import_cred()"; return NULL; } creds = cli_credentials_init(session_info); if (!creds) { *reason = "Out of memory in cli_credentials_init()"; return NULL; } session_info->credentials = creds; cli_credentials_set_conf(creds, lp_ctx); /* Just so we don't segfault trying to get at a username */ cli_credentials_set_anonymous(creds); ret = cli_credentials_set_client_gss_creds(creds, lp_ctx, cred_handle, CRED_SPECIFIED, &error_string); if (ret) { *reason = talloc_asprintf(mem_ctx, "Failed to set pipe forwarded" "creds: %s\n", error_string); return NULL; } /* This credential handle isn't useful for password * authentication, so ensure nobody tries to do that */ cli_credentials_set_kerberos_state(creds, CRED_MUST_USE_KERBEROS); } return session_info; }
static int ejs_cli_ssetup(MprVarHandle eid, int argc, MprVar **argv) { struct smbcli_transport *transport; struct smbcli_session *session; struct smb_composite_sesssetup setup; struct cli_credentials *creds; NTSTATUS status; int result = -1; /* Argument parsing */ if (argc < 1 || argc > 4) { ejsSetErrorMsg(eid, "session_setup invalid arguments"); return -1; } if (!mprVarIsPtr(argv[0]->type)) { ejsSetErrorMsg(eid, "first arg is not a connect handle"); return -1; } transport = argv[0]->ptr; creds = cli_credentials_init(transport); cli_credentials_set_conf(creds); if (argc == 4) { /* DOMAIN, USERNAME, PASSWORD form */ if (!mprVarIsString(argv[1]->type)) { ejsSetErrorMsg(eid, "arg 1 must be a string"); goto done; } cli_credentials_set_domain(creds, argv[1]->string, CRED_SPECIFIED); if (!mprVarIsString(argv[2]->type)) { ejsSetErrorMsg(eid, "arg 2 must be a string"); goto done; } cli_credentials_set_username(creds, argv[2]->string, CRED_SPECIFIED); if (!mprVarIsString(argv[3]->type)) { ejsSetErrorMsg(eid, "arg 3 must be a string"); goto done; } cli_credentials_set_password(creds, argv[3]->string, CRED_SPECIFIED); } else if (argc == 3) { /* USERNAME, PASSWORD form */ if (!mprVarIsString(argv[1]->type)) { ejsSetErrorMsg(eid, "arg1 must be a string"); goto done; } cli_credentials_set_username(creds, argv[1]->string, CRED_SPECIFIED); if (!mprVarIsString(argv[2]->type)) { ejsSetErrorMsg(eid, "arg2 must be a string"); goto done; } cli_credentials_set_password(creds, argv[2]->string, CRED_SPECIFIED); } else if (argc == 2) { /* DOMAIN/USERNAME%PASSWORD form */ cli_credentials_parse_string(creds, argv[1]->string, CRED_SPECIFIED); } else { /* Anonymous connection */ cli_credentials_set_anonymous(creds); } /* Do session setup */ session = smbcli_session_init(transport, transport, False); if (!session) { ejsSetErrorMsg(eid, "session init failed"); return -1; } setup.in.sesskey = transport->negotiate.sesskey; setup.in.capabilities = transport->negotiate.capabilities; setup.in.credentials = creds; setup.in.workgroup = lp_workgroup(); status = smb_composite_sesssetup(session, &setup); if (!NT_STATUS_IS_OK(status)) { ejsSetErrorMsg(eid, "session_setup: %s", nt_errstr(status)); return -1; } session->vuid = setup.out.vuid; /* Return a session object */ mpr_Return(eid, mprCreatePtrVar(session)); result = 0; done: talloc_free(creds); return result; }
static NTSTATUS server_check_password(struct auth_method_context *ctx, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, struct auth_serversupplied_info **_server_info) { NTSTATUS nt_status; struct auth_serversupplied_info *server_info; struct cli_credentials *creds; struct smb_composite_sesssetup session_setup; struct smbcli_session *session = talloc_get_type(ctx->private_data, struct smbcli_session); creds = cli_credentials_init(mem_ctx); NT_STATUS_HAVE_NO_MEMORY(creds); cli_credentials_set_username(creds, user_info->client.account_name, CRED_SPECIFIED); cli_credentials_set_domain(creds, user_info->client.domain_name, CRED_SPECIFIED); switch (user_info->password_state) { case AUTH_PASSWORD_PLAIN: cli_credentials_set_password(creds, user_info->password.plaintext, CRED_SPECIFIED); break; case AUTH_PASSWORD_HASH: cli_credentials_set_nt_hash(creds, user_info->password.hash.nt, CRED_SPECIFIED); break; case AUTH_PASSWORD_RESPONSE: cli_credentials_set_ntlm_response(creds, &user_info->password.response.lanman, &user_info->password.response.nt, CRED_SPECIFIED); break; } session_setup.in.sesskey = session->transport->negotiate.sesskey; session_setup.in.capabilities = session->transport->negotiate.capabilities; session_setup.in.credentials = creds; session_setup.in.workgroup = ""; /* Only used with SPNEGO, which we are not doing */ session_setup.in.gensec_settings = lp_gensec_settings(session, ctx->auth_ctx->lp_ctx); /* Check password with remove server - this should be async some day */ nt_status = smb_composite_sesssetup(session, &session_setup); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } server_info = talloc(mem_ctx, struct auth_serversupplied_info); NT_STATUS_HAVE_NO_MEMORY(server_info); server_info->account_sid = dom_sid_parse_talloc(server_info, SID_NT_ANONYMOUS); NT_STATUS_HAVE_NO_MEMORY(server_info->account_sid); /* is this correct? */ server_info->primary_group_sid = dom_sid_parse_talloc(server_info, SID_BUILTIN_GUESTS); NT_STATUS_HAVE_NO_MEMORY(server_info->primary_group_sid); server_info->n_domain_groups = 0; server_info->domain_groups = NULL; /* annoying, but the Anonymous really does have a session key, and it is all zeros! */ server_info->user_session_key = data_blob(NULL, 0); server_info->lm_session_key = data_blob(NULL, 0); server_info->account_name = talloc_strdup(server_info, user_info->client.account_name); NT_STATUS_HAVE_NO_MEMORY(server_info->account_name); server_info->domain_name = talloc_strdup(server_info, user_info->client.domain_name); NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name); server_info->full_name = NULL; server_info->logon_script = talloc_strdup(server_info, ""); NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script); server_info->profile_path = talloc_strdup(server_info, ""); NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path); server_info->home_directory = talloc_strdup(server_info, ""); NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory); server_info->home_drive = talloc_strdup(server_info, ""); NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive); server_info->last_logon = 0; server_info->last_logoff = 0; server_info->acct_expiry = 0; server_info->last_password_change = 0; server_info->allow_password_change = 0; server_info->force_password_change = 0; server_info->logon_count = 0; server_info->bad_password_count = 0; server_info->acct_flags = ACB_NORMAL; server_info->authenticated = false; *_server_info = server_info; return nt_status; }
/**************************************************************************** main program ****************************************************************************/ int main(int argc,char *argv[]) { char *share[NSERVERS]; int opt; int seed, server; int username_count=0; struct tevent_context *ev; struct loadparm_context *lp_ctx; poptContext pc; int argc_new, i; char **argv_new; enum {OPT_UNCLIST=1000}; struct poptOption long_options[] = { POPT_AUTOHELP {"seed", 0, POPT_ARG_INT, &seed, 0, "Seed to use for randomizer", NULL}, {"num-ops", 0, POPT_ARG_INT, &numops, 0, "num ops", NULL}, {"lockrange", 0, POPT_ARG_INT, &lock_range,0, "locking range", NULL}, {"lockbase", 0, POPT_ARG_INT, &lock_base, 0, "locking base", NULL}, {"minlength", 0, POPT_ARG_INT, &min_length,0, "min lock length", NULL}, {"hidefails", 0, POPT_ARG_NONE, &hide_unlock_fails,0,"hide unlock fails", NULL}, {"oplocks", 0, POPT_ARG_NONE, &use_oplocks,0, "use oplocks", NULL}, {"showall", 0, POPT_ARG_NONE, &showall, 0, "display all operations", NULL}, {"analyse", 0, POPT_ARG_NONE, &analyze, 0, "do backtrack analysis", NULL}, {"zerozero", 0, POPT_ARG_NONE, &zero_zero, 0, "do zero/zero lock", NULL}, {"exacterrors", 0, POPT_ARG_NONE, &exact_error_codes,0,"use exact error codes", NULL}, {"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL}, { "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "[DOMAIN/]USERNAME[%PASSWORD]" }, POPT_COMMON_SAMBA POPT_COMMON_CONNECTION POPT_COMMON_CREDENTIALS POPT_COMMON_VERSION { NULL } }; setlinebuf(stdout); seed = time(NULL); pc = poptGetContext("locktest", argc, (const char **) argv, long_options, POPT_CONTEXT_KEEP_FIRST); poptSetOtherOptionHelp(pc, "<unc1> <unc2>"); lp_ctx = cmdline_lp_ctx; servers[0] = cli_credentials_init(talloc_autofree_context()); servers[1] = cli_credentials_init(talloc_autofree_context()); cli_credentials_guess(servers[0], lp_ctx); cli_credentials_guess(servers[1], lp_ctx); while((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case OPT_UNCLIST: lp_set_cmdline(cmdline_lp_ctx, "torture:unclist", poptGetOptArg(pc)); break; case 'U': if (username_count == 2) { usage(pc); exit(1); } cli_credentials_parse_string(servers[username_count], poptGetOptArg(pc), CRED_SPECIFIED); username_count++; break; } } argv_new = discard_const_p(char *, poptGetArgs(pc)); argc_new = argc; for (i=0; i<argc; i++) { if (argv_new[i] == NULL) { argc_new = i; break; } } if (!(argc_new >= 3)) { usage(pc); exit(1); } setup_logging("locktest", DEBUG_STDOUT); for (server=0;server<NSERVERS;server++) { share[server] = argv_new[1+server]; all_string_sub(share[server],"/","\\",0); } lp_ctx = cmdline_lp_ctx; if (username_count == 0) { usage(pc); return -1; } if (username_count == 1) { servers[1] = servers[0]; } ev = s4_event_context_init(talloc_autofree_context()); gensec_init(lp_ctx); DEBUG(0,("seed=%u base=%d range=%d min_length=%d\n", seed, lock_base, lock_range, min_length)); srandom(seed); return test_locks(ev, lp_ctx, NULL, share); }
/* Get some basic (and authorization) information about the user on * this session. This uses either the PAC (if present) or a local * database lookup */ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, struct auth_session_info **_session_info) { NTSTATUS nt_status; TALLOC_CTX *tmp_ctx; struct gensec_gssapi_state *gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state); struct auth_session_info *session_info = NULL; OM_uint32 maj_stat, min_stat; DATA_BLOB pac_blob, *pac_blob_ptr = NULL; gss_buffer_desc name_token; char *principal_string; tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gssapi_session_info context"); NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); maj_stat = gss_display_name (&min_stat, gensec_gssapi_state->client_name, &name_token, NULL); if (GSS_ERROR(maj_stat)) { DEBUG(1, ("GSS display_name failed: %s\n", gssapi_error_string(tmp_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); talloc_free(tmp_ctx); return NT_STATUS_FOOBAR; } principal_string = talloc_strndup(tmp_ctx, (const char *)name_token.value, name_token.length); gss_release_buffer(&min_stat, &name_token); if (!principal_string) { talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } nt_status = gssapi_obtain_pac_blob(tmp_ctx, gensec_gssapi_state->gssapi_context, gensec_gssapi_state->client_name, &pac_blob); /* IF we have the PAC - otherwise we need to get this * data from elsewere - local ldb, or (TODO) lookup of some * kind... */ if (NT_STATUS_IS_OK(nt_status)) { pac_blob_ptr = &pac_blob; } nt_status = gensec_generate_session_info_pac(tmp_ctx, gensec_security, gensec_gssapi_state->smb_krb5_context, pac_blob_ptr, principal_string, gensec_get_remote_address(gensec_security), &session_info); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(tmp_ctx); return nt_status; } nt_status = gensec_gssapi_session_key(gensec_security, session_info, &session_info->session_key); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(tmp_ctx); return nt_status; } if (gensec_gssapi_state->gss_got_flags & GSS_C_DELEG_FLAG && gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) { krb5_error_code ret; const char *error_string; DEBUG(10, ("gensec_gssapi: delegated credentials supplied by client\n")); session_info->credentials = cli_credentials_init(session_info); if (!session_info->credentials) { talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } cli_credentials_set_conf(session_info->credentials, gensec_security->settings->lp_ctx); /* Just so we don't segfault trying to get at a username */ cli_credentials_set_anonymous(session_info->credentials); ret = cli_credentials_set_client_gss_creds(session_info->credentials, gensec_security->settings->lp_ctx, gensec_gssapi_state->delegated_cred_handle, CRED_SPECIFIED, &error_string); if (ret) { talloc_free(tmp_ctx); DEBUG(2,("Failed to get gss creds: %s\n", error_string)); return NT_STATUS_NO_MEMORY; } /* This credential handle isn't useful for password authentication, so ensure nobody tries to do that */ cli_credentials_set_kerberos_state(session_info->credentials, CRED_MUST_USE_KERBEROS); /* It has been taken from this place... */ gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL; } else { DEBUG(10, ("gensec_gssapi: NO delegated credentials supplied by client\n")); } *_session_info = talloc_steal(mem_ctx, session_info); talloc_free(tmp_ctx); return NT_STATUS_OK; }
NTSTATUS cli_credentials_update_all_keytabs(TALLOC_CTX *parent_ctx) { TALLOC_CTX *mem_ctx; int ldb_ret; struct ldb_context *ldb; struct ldb_message **msgs; const char *attrs[] = { NULL }; struct cli_credentials *creds; const char *filter; NTSTATUS status; int i, ret; mem_ctx = talloc_new(parent_ctx); if (!mem_ctx) { return NT_STATUS_NO_MEMORY; } /* Local secrets are stored in secrets.ldb */ ldb = secrets_db_connect(mem_ctx); if (!ldb) { DEBUG(1, ("Could not open secrets.ldb\n")); talloc_free(mem_ctx); return NT_STATUS_ACCESS_DENIED; } /* search for the secret record, but only of things we can * actually update */ ldb_ret = gendb_search(ldb, mem_ctx, NULL, &msgs, attrs, "(&(objectClass=kerberosSecret)(|(secret=*)(ntPwdHash=*)))"); if (ldb_ret == -1) { DEBUG(1, ("Error looking for kerberos type secrets to push into a keytab:: %s", ldb_errstring(ldb))); talloc_free(mem_ctx); return NT_STATUS_INTERNAL_DB_CORRUPTION; } for (i=0; i < ldb_ret; i++) { /* Make a credentials structure from it */ creds = cli_credentials_init(mem_ctx); if (!creds) { DEBUG(1, ("cli_credentials_init failed!")); talloc_free(mem_ctx); return NT_STATUS_NO_MEMORY; } cli_credentials_set_conf(creds); filter = talloc_asprintf(mem_ctx, "dn=%s", ldb_dn_get_linearized(msgs[i]->dn)); status = cli_credentials_set_secrets(creds, NULL, filter); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to read secrets for keytab update for %s\n", filter)); continue; } ret = cli_credentials_update_keytab(creds); if (ret != 0) { DEBUG(1, ("Failed to update keytab for %s\n", filter)); continue; } } return NT_STATUS_OK; }
/* Hook to allow GENSEC to handle blob-based authentication * mechanisms, without directly linking the mechansim code */ static NTSTATUS prepare_gensec(TALLOC_CTX *mem_ctx, struct gensec_security **gensec_context) { NTSTATUS status; struct loadparm_context *lp_ctx; struct tevent_context *event_ctx; TALLOC_CTX *frame = talloc_stackframe(); struct gensec_security *gensec_ctx; struct imessaging_context *msg_ctx; struct cli_credentials *server_credentials; lp_ctx = loadparm_init_s3(frame, loadparm_s3_context()); if (lp_ctx == NULL) { DEBUG(1, ("loadparm_init_s3 failed\n")); TALLOC_FREE(frame); return NT_STATUS_INVALID_SERVER_STATE; } event_ctx = s4_event_context_init(frame); if (event_ctx == NULL) { DEBUG(1, ("s4_event_context_init failed\n")); TALLOC_FREE(frame); return NT_STATUS_INVALID_SERVER_STATE; } msg_ctx = imessaging_client_init(frame, lp_ctx, event_ctx); if (msg_ctx == NULL) { DEBUG(1, ("imessaging_init failed\n")); TALLOC_FREE(frame); return NT_STATUS_INVALID_SERVER_STATE; } server_credentials = cli_credentials_init(frame); if (!server_credentials) { DEBUG(1, ("Failed to init server credentials")); TALLOC_FREE(frame); return NT_STATUS_INVALID_SERVER_STATE; } cli_credentials_set_conf(server_credentials, lp_ctx); status = cli_credentials_set_machine_account(server_credentials, lp_ctx); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Failed to obtain server credentials, perhaps a standalone server?: %s\n", nt_errstr(status))); talloc_free(server_credentials); server_credentials = NULL; } status = samba_server_gensec_start(mem_ctx, event_ctx, msg_ctx, lp_ctx, server_credentials, "cifs", &gensec_ctx); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status))); TALLOC_FREE(frame); return status; } talloc_reparent(frame, gensec_ctx, msg_ctx); talloc_reparent(frame, gensec_ctx, event_ctx); talloc_reparent(frame, gensec_ctx, lp_ctx); talloc_reparent(frame, gensec_ctx, server_credentials); gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SESSION_KEY); gensec_want_feature(gensec_ctx, GENSEC_FEATURE_UNIX_TOKEN); *gensec_context = gensec_ctx; TALLOC_FREE(frame); return status; }
static int set_ldap_credentials(struct ldb_context *ldb, bool use_external) { const char *secrets_ldb_path, *sam_ldb_path; char *private_dir, *p, *error_string; struct ldb_context *secrets_ldb; struct cli_credentials *cred; struct loadparm_context *lp_ctx = ldb_get_opaque(ldb, "loadparm"); TALLOC_CTX *tmp_ctx = talloc_new(ldb); if (!tmp_ctx) { return ldb_oom(ldb); } cred = cli_credentials_init(ldb); if (!cred) { talloc_free(tmp_ctx); return ldb_oom(ldb); } cli_credentials_set_anonymous(cred); if (use_external) { cli_credentials_set_forced_sasl_mech(cred, "EXTERNAL"); } else { cli_credentials_set_forced_sasl_mech(cred, "DIGEST-MD5"); /* * We don't want to use krb5 to talk to our samdb - recursion * here would be bad, and this account isn't in the KDC * anyway */ cli_credentials_set_kerberos_state(cred, CRED_DONT_USE_KERBEROS); /* * Work out where *our* secrets.ldb is. It must be in * the same directory as sam.ldb */ sam_ldb_path = (const char *)ldb_get_opaque(ldb, "ldb_url"); if (!sam_ldb_path) { talloc_free(tmp_ctx); return ldb_operr(ldb); } if (strncmp("tdb://", sam_ldb_path, 6) == 0) { sam_ldb_path += 6; } private_dir = talloc_strdup(tmp_ctx, sam_ldb_path); p = strrchr(private_dir, '/'); if (p) { *p = '\0'; } else { private_dir = talloc_strdup(tmp_ctx, "."); } secrets_ldb_path = talloc_asprintf(private_dir, "tdb://%s/secrets.ldb", private_dir); if (!secrets_ldb_path) { talloc_free(tmp_ctx); return ldb_oom(ldb); } /* * Now that we have found the location, connect to * secrets.ldb so we can read the SamDB Credentials * record */ secrets_ldb = ldb_wrap_connect(tmp_ctx, NULL, lp_ctx, secrets_ldb_path, NULL, NULL, 0); if (!NT_STATUS_IS_OK(cli_credentials_set_secrets(cred, NULL, secrets_ldb, NULL, SECRETS_LDAP_FILTER, &error_string))) { ldb_asprintf_errstring(ldb, "Failed to read LDAP backend password from %s", secrets_ldb_path); talloc_free(tmp_ctx); return LDB_ERR_STRONG_AUTH_REQUIRED; } } /* * Finally overwrite any supplied credentials with * these ones, as only secrets.ldb contains the magic * credentials to talk on the ldapi socket */ if (ldb_set_opaque(ldb, "credentials", cred)) { talloc_free(tmp_ctx); return ldb_operr(ldb); } talloc_free(tmp_ctx); return LDB_SUCCESS; }
static bool test_schannel_anonymous_setPassword(struct torture_context *tctx, uint32_t dcerpc_flags, bool use2) { NTSTATUS status, result; const char *binding = torture_setting_string(tctx, "binding", NULL); struct dcerpc_binding *b; struct dcerpc_pipe *p = NULL; struct cli_credentials *credentials; bool ok = true; credentials = cli_credentials_init(NULL); torture_assert(tctx, credentials != NULL, "Bad credentials"); cli_credentials_set_anonymous(credentials); status = dcerpc_parse_binding(tctx, binding, &b); torture_assert_ntstatus_ok(tctx, status, "Bad binding string"); status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS); torture_assert_ntstatus_ok(tctx, status, "set flags"); status = dcerpc_pipe_connect_b(tctx, &p, b, &ndr_table_netlogon, credentials, tctx->ev, tctx->lp_ctx); torture_assert_ntstatus_ok(tctx, status, "Failed to connect without schannel"); if (use2) { struct netr_ServerPasswordSet2 r = {}; struct netr_Authenticator credential = {}; struct netr_Authenticator return_authenticator = {}; struct netr_CryptPassword new_password = {}; r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME); r.in.secure_channel_type = 0; r.in.computer_name = TEST_MACHINE_NAME; r.in.credential = &credential; r.in.new_password = &new_password; r.out.return_authenticator = &return_authenticator; status = dcerpc_netr_ServerPasswordSet2_r(p->binding_handle, tctx, &r); result = r.out.result; } else { struct netr_ServerPasswordSet r = {}; struct netr_Authenticator credential = {}; struct netr_Authenticator return_authenticator = {}; struct samr_Password new_password = {}; r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME); r.in.secure_channel_type = 0; r.in.computer_name = TEST_MACHINE_NAME; r.in.credential = &credential; r.in.new_password = &new_password; r.out.return_authenticator = &return_authenticator; status = dcerpc_netr_ServerPasswordSet_r(p->binding_handle, tctx, &r); result = r.out.result; } torture_assert_ntstatus_ok(tctx, status, "ServerPasswordSet failed"); if (NT_STATUS_IS_OK(result)) { torture_fail(tctx, "unexpectedly received NT_STATUS_OK"); } return ok; }
static void popt_common_credentials_callback(poptContext con, enum poptCallbackReason reason, const struct poptOption *opt, const char *arg, const void *data) { if (reason == POPT_CALLBACK_REASON_PRE) { cmdline_credentials = cli_credentials_init(talloc_autofree_context()); return; } if (reason == POPT_CALLBACK_REASON_POST) { cli_credentials_guess(cmdline_credentials, cmdline_lp_ctx); if (!dont_ask) { cli_credentials_set_cmdline_callbacks(cmdline_credentials); } return; } switch(opt->val) { case 'U': { char *lp; cli_credentials_parse_string(cmdline_credentials, arg, CRED_SPECIFIED); /* This breaks the abstraction, including the const above */ if ((lp=strchr_m(arg,'%'))) { lp[0]='\0'; lp++; /* Try to prevent this showing up in ps */ memset(lp,0,strlen(lp)); } } break; case OPT_PASSWORD: cli_credentials_set_password(cmdline_credentials, arg, CRED_SPECIFIED); /* Try to prevent this showing up in ps */ memset(discard_const(arg),0,strlen(arg)); break; case 'A': cli_credentials_parse_file(cmdline_credentials, arg, CRED_SPECIFIED); break; case 'P': /* Later, after this is all over, get the machine account details from the secrets.ldb */ cli_credentials_set_machine_account_pending(cmdline_credentials, cmdline_lp_ctx); break; case OPT_KERBEROS: { bool use_kerberos = true; /* Force us to only use kerberos */ if (arg) { if (!set_boolean(arg, &use_kerberos)) { fprintf(stderr, "Error parsing -k %s\n", arg); exit(1); break; } } cli_credentials_set_kerberos_state(cmdline_credentials, use_kerberos ? CRED_MUST_USE_KERBEROS : CRED_DONT_USE_KERBEROS); break; } case OPT_SIMPLE_BIND_DN: cli_credentials_set_bind_dn(cmdline_credentials, arg); break; } }
static bool torture_rpc_spoolss_access_setup_common(struct torture_context *tctx, struct torture_access_context *t) { void *testuser; const char *testuser_passwd; struct cli_credentials *test_credentials; struct dom_sid *test_sid; struct dcerpc_pipe *p; const char *printername; const char *binding = torture_setting_string(tctx, "binding", NULL); struct dcerpc_pipe *spoolss_pipe; testuser = torture_create_testuser_max_pwlen(tctx, t->user.username, torture_setting_string(tctx, "workgroup", NULL), ACB_NORMAL, &testuser_passwd, 32); if (!testuser) { torture_fail(tctx, "Failed to create test user"); } test_credentials = cli_credentials_init(tctx); cli_credentials_set_workstation(test_credentials, "localhost", CRED_SPECIFIED); cli_credentials_set_domain(test_credentials, lpcfg_workgroup(tctx->lp_ctx), CRED_SPECIFIED); cli_credentials_set_username(test_credentials, t->user.username, CRED_SPECIFIED); cli_credentials_set_password(test_credentials, testuser_passwd, CRED_SPECIFIED); test_sid = discard_const_p(struct dom_sid, torture_join_user_sid(testuser)); if (t->user.num_builtin_memberships) { struct dcerpc_pipe *samr_pipe = torture_join_samr_pipe(testuser); torture_assert(tctx, spoolss_access_setup_membership(tctx, samr_pipe, t->user.num_builtin_memberships, t->user.builtin_memberships, test_sid), "failed to setup membership"); } if (t->user.num_privs) { struct dcerpc_pipe *lsa_pipe; torture_assert_ntstatus_ok(tctx, torture_rpc_connection(tctx, &lsa_pipe, &ndr_table_lsarpc), "Error connecting to server"); torture_assert(tctx, spoolss_access_setup_privs(tctx, lsa_pipe, t->user.num_privs, t->user.privs, test_sid, &t->user.privs_present), "failed to setup privs"); talloc_free(lsa_pipe); } torture_assert_ntstatus_ok(tctx, torture_rpc_connection(tctx, &spoolss_pipe, &ndr_table_spoolss), "Error connecting to server"); torture_assert(tctx, test_EnumPrinters_findone(tctx, spoolss_pipe, &printername), "failed to enumerate printers"); if (t->user.sd && printername) { torture_assert(tctx, spoolss_access_setup_sd(tctx, spoolss_pipe, printername, test_sid, &t->sd_orig), "failed to setup sd"); } talloc_free(spoolss_pipe); torture_assert_ntstatus_ok(tctx, dcerpc_pipe_connect(tctx, &p, binding, &ndr_table_spoolss, test_credentials, tctx->ev, tctx->lp_ctx), "Error connecting to server"); t->spoolss_pipe = p; t->printername = printername; t->user.testuser = testuser; return true; }
static void manage_gensec_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) { DATA_BLOB in; DATA_BLOB out = data_blob(NULL, 0); char *out_base64 = NULL; const char *reply_arg = NULL; struct gensec_ntlm_state { struct gensec_security *gensec_state; const char *set_password; }; struct gensec_ntlm_state *state; struct tevent_context *ev; struct imessaging_context *msg; NTSTATUS nt_status; bool first = false; const char *reply_code; struct cli_credentials *creds; static char *want_feature_list = NULL; static DATA_BLOB session_key; TALLOC_CTX *mem_ctx; if (*private1) { state = (struct gensec_ntlm_state *)*private1; } else { state = talloc_zero(NULL, struct gensec_ntlm_state); if (!state) { mux_printf(mux_id, "BH No Memory\n"); exit(1); } *private1 = state; if (opt_password) { state->set_password = opt_password; } } if (strlen(buf) < 2) { DEBUG(1, ("query [%s] invalid", buf)); mux_printf(mux_id, "BH Query invalid\n"); return; } if (strlen(buf) > 3) { if(strncmp(buf, "SF ", 3) == 0) { DEBUG(10, ("Setting flags to negotiate\n")); talloc_free(want_feature_list); want_feature_list = talloc_strndup(state, buf+3, strlen(buf)-3); mux_printf(mux_id, "OK\n"); return; } in = base64_decode_data_blob(buf + 3); } else { in = data_blob(NULL, 0); } if (strncmp(buf, "YR", 2) == 0) { if (state->gensec_state) { talloc_free(state->gensec_state); state->gensec_state = NULL; } } else if ( (strncmp(buf, "OK", 2) == 0)) { /* Just return BH, like ntlm_auth from Samba 3 does. */ mux_printf(mux_id, "BH Command expected\n"); data_blob_free(&in); return; } else if ( (strncmp(buf, "TT ", 3) != 0) && (strncmp(buf, "KK ", 3) != 0) && (strncmp(buf, "AF ", 3) != 0) && (strncmp(buf, "NA ", 3) != 0) && (strncmp(buf, "UG", 2) != 0) && (strncmp(buf, "PW ", 3) != 0) && (strncmp(buf, "GK", 2) != 0) && (strncmp(buf, "GF", 2) != 0)) { DEBUG(1, ("SPNEGO request [%s] invalid\n", buf)); mux_printf(mux_id, "BH SPNEGO request invalid\n"); data_blob_free(&in); return; } ev = s4_event_context_init(state); if (!ev) { exit(1); } mem_ctx = talloc_named(NULL, 0, "manage_gensec_request internal mem_ctx"); /* setup gensec */ if (!(state->gensec_state)) { switch (stdio_helper_mode) { case GSS_SPNEGO_CLIENT: case NTLMSSP_CLIENT_1: /* setup the client side */ nt_status = gensec_client_start(NULL, &state->gensec_state, ev, lpcfg_gensec_settings(NULL, lp_ctx)); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); exit(1); } break; case GSS_SPNEGO_SERVER: case SQUID_2_5_NTLMSSP: { const char *winbind_method[] = { "winbind", NULL }; struct auth4_context *auth_context; msg = imessaging_client_init(state, lpcfg_imessaging_path(state, lp_ctx), ev); if (!msg) { talloc_free(mem_ctx); exit(1); } nt_status = auth_context_create_methods(mem_ctx, winbind_method, ev, msg, lp_ctx, NULL, &auth_context); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); exit(1); } if (!NT_STATUS_IS_OK(gensec_server_start(state, ev, lpcfg_gensec_settings(state, lp_ctx), auth_context, &state->gensec_state))) { talloc_free(mem_ctx); exit(1); } break; } default: talloc_free(mem_ctx); abort(); } creds = cli_credentials_init(state->gensec_state); cli_credentials_set_conf(creds, lp_ctx); if (opt_username) { cli_credentials_set_username(creds, opt_username, CRED_SPECIFIED); } if (opt_domain) { cli_credentials_set_domain(creds, opt_domain, CRED_SPECIFIED); } if (state->set_password) { cli_credentials_set_password(creds, state->set_password, CRED_SPECIFIED); } else { cli_credentials_set_password_callback(creds, get_password); creds->priv_data = (void*)(uintptr_t)mux_id; } if (opt_workstation) { cli_credentials_set_workstation(creds, opt_workstation, CRED_SPECIFIED); } switch (stdio_helper_mode) { case GSS_SPNEGO_SERVER: case SQUID_2_5_NTLMSSP: cli_credentials_set_machine_account(creds, lp_ctx); break; default: break; } gensec_set_credentials(state->gensec_state, creds); gensec_want_feature_list(state->gensec_state, want_feature_list); switch (stdio_helper_mode) { case GSS_SPNEGO_CLIENT: case GSS_SPNEGO_SERVER: nt_status = gensec_start_mech_by_oid(state->gensec_state, GENSEC_OID_SPNEGO); if (!in.length) { first = true; } break; case NTLMSSP_CLIENT_1: if (!in.length) { first = true; } /* fall through */ case SQUID_2_5_NTLMSSP: nt_status = gensec_start_mech_by_oid(state->gensec_state, GENSEC_OID_NTLMSSP); break; default: talloc_free(mem_ctx); abort(); } if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(1, ("GENSEC mech failed to start: %s\n", nt_errstr(nt_status))); mux_printf(mux_id, "BH GENSEC mech failed to start\n"); talloc_free(mem_ctx); return; } } /* update */ if (strncmp(buf, "PW ", 3) == 0) { state->set_password = talloc_strndup(state, (const char *)in.data, in.length); cli_credentials_set_password(gensec_get_credentials(state->gensec_state), state->set_password, CRED_SPECIFIED); mux_printf(mux_id, "OK\n"); data_blob_free(&in); talloc_free(mem_ctx); return; } if (strncmp(buf, "UG", 2) == 0) { int i; char *grouplist = NULL; struct auth_session_info *session_info; nt_status = gensec_session_info(state->gensec_state, mem_ctx, &session_info); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(1, ("gensec_session_info failed: %s\n", nt_errstr(nt_status))); mux_printf(mux_id, "BH %s\n", nt_errstr(nt_status)); data_blob_free(&in); talloc_free(mem_ctx); return; } /* get the string onto the context */ grouplist = talloc_strdup(mem_ctx, ""); for (i=0; i<session_info->security_token->num_sids; i++) { struct security_token *token = session_info->security_token; const char *sidstr = dom_sid_string(session_info, &token->sids[i]); grouplist = talloc_asprintf_append_buffer(grouplist, "%s,", sidstr); } mux_printf(mux_id, "GL %s\n", grouplist); talloc_free(session_info); data_blob_free(&in); talloc_free(mem_ctx); return; } if (strncmp(buf, "GK", 2) == 0) { char *base64_key; DEBUG(10, ("Requested session key\n")); nt_status = gensec_session_key(state->gensec_state, mem_ctx, &session_key); if(!NT_STATUS_IS_OK(nt_status)) { DEBUG(1, ("gensec_session_key failed: %s\n", nt_errstr(nt_status))); mux_printf(mux_id, "BH No session key\n"); talloc_free(mem_ctx); return; } else { base64_key = base64_encode_data_blob(state, session_key); mux_printf(mux_id, "GK %s\n", base64_key); talloc_free(base64_key); } talloc_free(mem_ctx); return; } if (strncmp(buf, "GF", 2) == 0) { struct ntlmssp_state *ntlmssp_state; uint32_t neg_flags; ntlmssp_state = talloc_get_type(state->gensec_state->private_data, struct ntlmssp_state); neg_flags = ntlmssp_state->neg_flags; DEBUG(10, ("Requested negotiated feature flags\n")); mux_printf(mux_id, "GF 0x%08x\n", neg_flags); return; } nt_status = gensec_update(state->gensec_state, mem_ctx, in, &out); /* don't leak 'bad password'/'no such user' info to the network client */ nt_status = nt_status_squash(nt_status); if (out.length) { out_base64 = base64_encode_data_blob(mem_ctx, out); } else { out_base64 = NULL; } if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { reply_arg = "*"; if (first) { reply_code = "YR"; } else if (state->gensec_state->gensec_role == GENSEC_CLIENT) { reply_code = "KK"; } else if (state->gensec_state->gensec_role == GENSEC_SERVER) { reply_code = "TT"; } else { abort(); } } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED)) { reply_code = "BH NT_STATUS_ACCESS_DENIED"; reply_arg = nt_errstr(nt_status); DEBUG(1, ("GENSEC login failed: %s\n", nt_errstr(nt_status))); } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_UNSUCCESSFUL)) { reply_code = "BH NT_STATUS_UNSUCCESSFUL"; reply_arg = nt_errstr(nt_status); DEBUG(1, ("GENSEC login failed: %s\n", nt_errstr(nt_status))); } else if (!NT_STATUS_IS_OK(nt_status)) { reply_code = "NA"; reply_arg = nt_errstr(nt_status); DEBUG(1, ("GENSEC login failed: %s\n", nt_errstr(nt_status))); } else if /* OK */ (state->gensec_state->gensec_role == GENSEC_SERVER) { struct auth_session_info *session_info; nt_status = gensec_session_info(state->gensec_state, mem_ctx, &session_info); if (!NT_STATUS_IS_OK(nt_status)) { reply_code = "BH Failed to retrive session info"; reply_arg = nt_errstr(nt_status); DEBUG(1, ("GENSEC failed to retrieve the session info: %s\n", nt_errstr(nt_status))); } else { reply_code = "AF"; reply_arg = talloc_asprintf(state->gensec_state, "%s%s%s", session_info->info->domain_name, lpcfg_winbind_separator(lp_ctx), session_info->info->account_name); talloc_free(session_info); } } else if (state->gensec_state->gensec_role == GENSEC_CLIENT) { reply_code = "AF"; reply_arg = out_base64; } else { abort(); } switch (stdio_helper_mode) { case GSS_SPNEGO_SERVER: mux_printf(mux_id, "%s %s %s\n", reply_code, out_base64 ? out_base64 : "*", reply_arg ? reply_arg : "*"); break; default: if (out_base64) { mux_printf(mux_id, "%s %s\n", reply_code, out_base64); } else if (reply_arg) { mux_printf(mux_id, "%s %s\n", reply_code, reply_arg); } else { mux_printf(mux_id, "%s\n", reply_code); } } talloc_free(mem_ctx); return; }