s3: libsmb: In cli_list_old_send(), push state->mask into the packet, not just mask.
[Samba.git] / source3 / winbindd / winbindd_getgrnam.c
blob20ac70c9b7131b88a3b06bfa29ab8bf3a2eb5e3c
1 /*
2 Unix SMB/CIFS implementation.
3 async implementation of WINBINDD_GETGRNAM
4 Copyright (C) Volker Lendecke 2009
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "winbindd.h"
22 #include "libcli/security/dom_sid.h"
23 #include "lib/util/string_wrappers.h"
25 struct winbindd_getgrnam_state {
26 struct tevent_context *ev;
27 fstring name_namespace, name_domain, name_group;
28 struct dom_sid sid;
29 const char *domname;
30 const char *name;
31 gid_t gid;
32 struct db_context *members;
35 static void winbindd_getgrnam_lookupname_done(struct tevent_req *subreq);
36 static void winbindd_getgrnam_done(struct tevent_req *subreq);
38 struct tevent_req *winbindd_getgrnam_send(TALLOC_CTX *mem_ctx,
39 struct tevent_context *ev,
40 struct winbindd_cli_state *cli,
41 struct winbindd_request *request)
43 struct tevent_req *req, *subreq;
44 struct winbindd_getgrnam_state *state;
45 char *tmp;
46 NTSTATUS nt_status;
47 bool ok;
49 req = tevent_req_create(mem_ctx, &state,
50 struct winbindd_getgrnam_state);
51 if (req == NULL) {
52 return NULL;
54 state->ev = ev;
56 /* Ensure null termination */
57 request->data.groupname[sizeof(request->data.groupname)-1]='\0';
59 D_NOTICE("[%s (%u)] Winbind external command GETGRNAM start.\n"
60 "Searching group name '%s'.\n",
61 cli->client_name,
62 (unsigned int)cli->pid,
63 request->data.groupname);
65 nt_status = normalize_name_unmap(state, request->data.groupname, &tmp);
66 /* If we didn't map anything in the above call, just reset the
67 tmp pointer to the original string */
68 if (!NT_STATUS_IS_OK(nt_status) &&
69 !NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED))
71 tmp = request->data.groupname;
74 /* Parse domain and groupname */
76 ok = parse_domain_user(tmp,
77 state->name_namespace,
78 state->name_domain,
79 state->name_group);
80 if (!ok) {
81 DBG_INFO("Could not parse domain user: %s\n", tmp);
82 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
83 return tevent_req_post(req, ev);
86 /* if no domain or our local domain and no local tdb group, default to
87 * our local domain for aliases */
89 if ( !*(state->name_domain) || strequal(state->name_domain,
90 get_global_sam_name()) ) {
91 fstrcpy(state->name_domain, get_global_sam_name());
94 subreq = wb_lookupname_send(state, ev,
95 state->name_namespace,
96 state->name_domain,
97 state->name_group,
98 0);
99 if (tevent_req_nomem(subreq, req)) {
100 return tevent_req_post(req, ev);
102 tevent_req_set_callback(subreq, winbindd_getgrnam_lookupname_done,
103 req);
104 return req;
107 static void winbindd_getgrnam_lookupname_done(struct tevent_req *subreq)
109 struct tevent_req *req = tevent_req_callback_data(
110 subreq, struct tevent_req);
111 struct winbindd_getgrnam_state *state = tevent_req_data(
112 req, struct winbindd_getgrnam_state);
113 enum lsa_SidType type;
114 NTSTATUS status;
116 status = wb_lookupname_recv(subreq, &state->sid, &type);
117 TALLOC_FREE(subreq);
118 if (tevent_req_nterror(req, status)) {
119 return;
122 switch (type) {
123 case SID_NAME_DOM_GRP:
124 case SID_NAME_ALIAS:
125 case SID_NAME_WKN_GRP:
127 * Also give user types a chance:
128 * These might be user sids mapped to the ID_TYPE_BOTH,
129 * and in that case we should construct a group struct.
131 case SID_NAME_USER:
132 case SID_NAME_COMPUTER:
133 break;
134 default:
135 tevent_req_nterror(req, NT_STATUS_NO_SUCH_GROUP);
136 return;
139 subreq = wb_getgrsid_send(state, state->ev, &state->sid,
140 lp_winbind_expand_groups());
141 if (tevent_req_nomem(subreq, req)) {
142 return;
144 tevent_req_set_callback(subreq, winbindd_getgrnam_done, req);
147 static void winbindd_getgrnam_done(struct tevent_req *subreq)
149 struct tevent_req *req = tevent_req_callback_data(
150 subreq, struct tevent_req);
151 struct winbindd_getgrnam_state *state = tevent_req_data(
152 req, struct winbindd_getgrnam_state);
153 NTSTATUS status;
155 status = wb_getgrsid_recv(subreq, state, &state->domname, &state->name,
156 &state->gid, &state->members);
157 TALLOC_FREE(subreq);
158 if (tevent_req_nterror(req, status)) {
159 return;
161 tevent_req_done(req);
164 NTSTATUS winbindd_getgrnam_recv(struct tevent_req *req,
165 struct winbindd_response *response)
167 struct winbindd_getgrnam_state *state = tevent_req_data(
168 req, struct winbindd_getgrnam_state);
169 NTSTATUS status;
170 int num_members;
171 char *buf;
173 if (tevent_req_is_nterror(req, &status)) {
174 struct dom_sid_buf sidbuf;
175 D_WARNING("Could not convert sid %s: %s\n",
176 dom_sid_str_buf(&state->sid, &sidbuf),
177 nt_errstr(status));
178 return status;
181 if (!fill_grent(talloc_tos(), &response->data.gr, state->domname,
182 state->name, state->gid)) {
183 D_WARNING("fill_grent failed\n");
184 return NT_STATUS_NO_MEMORY;
187 status = winbindd_print_groupmembers(state->members, response,
188 &num_members, &buf);
189 if (!NT_STATUS_IS_OK(status)) {
190 return status;
193 response->data.gr.num_gr_mem = (uint32_t)num_members;
195 /* Group membership lives at start of extra data */
197 response->data.gr.gr_mem_ofs = 0;
198 response->extra_data.data = buf;
199 response->length += talloc_get_size(response->extra_data.data);
201 D_NOTICE("Winbind external command GETGRNAM end.\n"
202 "Returning %"PRIu32" memmber(s).\n",
203 response->data.gr.num_gr_mem);
205 return NT_STATUS_OK;