From: Samuel Cabrero Date: Mon, 6 Feb 2023 17:20:32 +0000 (+0100) Subject: winbind:varlink: Implement get user record by uid X-Git-Tag: tevent-0.17.0~743 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=946a800c2198b57bd033d6efdbec05be18386239;p=thirdparty%2Fsamba.git winbind:varlink: Implement get user record by uid $> userdbctl -s org.samba.winbind user 21105 Enabled services: org.samba.winbind User name: AFOREST+user1 Disposition: regular Login OK: yes Password OK: no (none set) UID: 21105 GID: 20513 (unresolvable: No such process) Directory: /home/AFOREST/user1 Storage: classic Shell: /bin/bash Passwords: none Service: org.samba.winbind $> SYSTEMD_LOG_LEVEL=7 getent -spasswd:systemd passwd 21105 varlink: Setting state idle-client /run/systemd/userdb/org.samba.winbind: Sending message: {"method":"io.systemd.UserDatabase.GetUserRecord","parameters":{"uid":21105,"service":"org.samba.winbind"}} /run/systemd/userdb/org.samba.winbind: Changing state idle-client → awaiting-reply /run/systemd/userdb/org.samba.winbind: New incoming message: {"parameters":{"incomplete":false,"record":{"gid":20513,"homeDirectory":"/home/AFOREST/user1","service":"org.samba.winbind","shell":"/bin/bash","uid":21105,"userName":"AFOREST+user1"}}} /run/systemd/userdb/org.samba.winbind: Changing state awaiting-reply → processing-reply /run/systemd/userdb/org.samba.winbind: Changing state processing-reply → idle-client AFOREST+user1:x:21105:20513:AFOREST+user1:/home/AFOREST/user1:/bin/bash Signed-off-by: Samuel Cabrero Reviewed-by: Andreas Schneider --- diff --git a/source3/winbindd/winbindd_varlink.c b/source3/winbindd/winbindd_varlink.c index 02cffb84211..676c0f34f16 100644 --- a/source3/winbindd/winbindd_varlink.c +++ b/source3/winbindd/winbindd_varlink.c @@ -180,6 +180,14 @@ static long io_systemd_getuserrecord(VarlinkService *service, call, flags, parm_service); + } else if (parm_name == NULL && parm_uid >= 0) { + /* getpwuid */ + status = wb_vl_user_by_uid(state, + state->ev_ctx, + call, + flags, + parm_service, + parm_uid); } if (NT_STATUS_IS_ERR(status)) { diff --git a/source3/winbindd/winbindd_varlink.h b/source3/winbindd/winbindd_varlink.h index e26d14f737c..ffaa5accc4f 100644 --- a/source3/winbindd/winbindd_varlink.h +++ b/source3/winbindd/winbindd_varlink.h @@ -47,6 +47,12 @@ NTSTATUS wb_vl_user_enumerate(TALLOC_CTX *state, VarlinkCall *call, uint64_t flags, const char *service); +NTSTATUS wb_vl_user_by_uid(TALLOC_CTX *mem_ctx, + struct tevent_context *ev_ctx, + VarlinkCall *call, + uint64_t flags, + const char *service, + int64_t gid); bool winbind_setup_varlink(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx); diff --git a/source3/winbindd/winbindd_varlink_getuserrecord.c b/source3/winbindd/winbindd_varlink_getuserrecord.c index 85ccf3f2226..6bd6417fae5 100644 --- a/source3/winbindd/winbindd_varlink_getuserrecord.c +++ b/source3/winbindd/winbindd_varlink_getuserrecord.c @@ -352,3 +352,123 @@ fail: TALLOC_FREE(s); return status; } + +/****************************************************************************** + * User by uid + *****************************************************************************/ + +struct user_by_uid_state { + struct tevent_context *ev_ctx; + struct winbindd_request *fake_req; + struct winbindd_cli_state *fake_cli; + VarlinkCall *call; +}; + +static int user_by_uid_state_destructor(struct user_by_uid_state *s) +{ + if (s->call != NULL) { + s->call = varlink_call_unref(s->call); + } + + return 0; +} + +static void user_by_uid_getpwuid_done(struct tevent_req *req) +{ + struct user_by_uid_state *s = + tevent_req_callback_data(req, struct user_by_uid_state); + struct winbindd_response *response = NULL; + NTSTATUS status; + + /* winbindd_*_recv functions expect a talloc-allocated response */ + response = talloc_zero(s, struct winbindd_response); + if (response == NULL) { + DBG_ERR("No memory\n"); + varlink_call_reply_error( + s->call, + WB_VL_REPLY_ERROR_SERVICE_NOT_AVAILABLE, + NULL); + goto out; + } + + status = winbindd_getpwuid_recv(req, response); + TALLOC_FREE(req); + + if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) { + varlink_call_reply_error(s->call, + WB_VL_REPLY_ERROR_NO_RECORD_FOUND, + NULL); + goto out; + } else if (NT_STATUS_IS_ERR(status)) { + DBG_ERR("winbindd_getgrgid failed: %s\n", nt_errstr(status)); + varlink_call_reply_error( + s->call, + WB_VL_REPLY_ERROR_SERVICE_NOT_AVAILABLE, + NULL); + goto out; + } + + user_record_reply(s->call, &response->data.pw, false); + +out: + TALLOC_FREE(s); +} + +NTSTATUS wb_vl_user_by_uid(TALLOC_CTX *mem_ctx, + struct tevent_context *ev_ctx, + VarlinkCall *call, + uint64_t flags, + const char *service, + int64_t uid) +{ + struct user_by_uid_state *s = NULL; + struct tevent_req *req = NULL; + NTSTATUS status; + + s = talloc_zero(mem_ctx, struct user_by_uid_state); + if (s == NULL) { + DBG_ERR("No memory\n"); + return NT_STATUS_NO_MEMORY; + } + talloc_set_destructor(s, user_by_uid_state_destructor); + + s->fake_cli = talloc_zero(s, struct winbindd_cli_state); + if (s->fake_cli == NULL) { + DBG_ERR("No memory\n"); + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + s->fake_req = talloc_zero(s, struct winbindd_request); + if (s->fake_req == NULL) { + DBG_ERR("No memory\n"); + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + s->ev_ctx = ev_ctx; + s->call = varlink_call_ref(call); + + status = wb_vl_fake_cli_state(call, service, s->fake_cli); + if (NT_STATUS_IS_ERR(status)) { + DBG_ERR("Failed to create fake winbindd_cli_state: %s\n", + nt_errstr(status)); + goto fail; + } + + s->fake_req->cmd = WINBINDD_GETPWUID; + s->fake_req->data.uid = uid; + + req = winbindd_getpwuid_send(s, s->ev_ctx, s->fake_cli, s->fake_req); + if (req == NULL) { + DBG_ERR("No memory\n"); + status = NT_STATUS_NO_MEMORY; + goto fail; + } + tevent_req_set_callback(req, user_by_uid_getpwuid_done, s); + + return NT_STATUS_OK; +fail: + TALLOC_FREE(s); + return status; +}