s3-lsa: Fix static list of luids in our privileges implementation.
[Samba/ekacnet.git] / source3 / auth / server_info.c
blobf72cdbaae9a1cd36db2e0da6d1ab118e966d1ee9
1 /*
2 Unix SMB/CIFS implementation.
3 Authentication utility functions
4 Copyright (C) Volker Lendecke 2010
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 "../lib/crypto/arcfour.h"
23 #undef DBGC_CLASS
24 #define DBGC_CLASS DBGC_AUTH
26 /* FIXME: do we really still need this ? */
27 static int server_info_dtor(struct auth_serversupplied_info *server_info)
29 TALLOC_FREE(server_info->info3);
30 ZERO_STRUCTP(server_info);
31 return 0;
34 /***************************************************************************
35 Make a server_info struct. Free with TALLOC_FREE().
36 ***************************************************************************/
38 struct auth_serversupplied_info *make_server_info(TALLOC_CTX *mem_ctx)
40 struct auth_serversupplied_info *result;
42 result = TALLOC_ZERO_P(mem_ctx, struct auth_serversupplied_info);
43 if (result == NULL) {
44 DEBUG(0, ("talloc failed\n"));
45 return NULL;
48 talloc_set_destructor(result, server_info_dtor);
50 /* Initialise the uid and gid values to something non-zero
51 which may save us from giving away root access if there
52 is a bug in allocating these fields. */
54 result->utok.uid = -1;
55 result->utok.gid = -1;
56 return result;
59 /****************************************************************************
60 inits a netr_SamInfo2 structure from an auth_serversupplied_info. sam2 must
61 already be initialized and is used as the talloc parent for its members.
62 *****************************************************************************/
64 NTSTATUS serverinfo_to_SamInfo2(struct auth_serversupplied_info *server_info,
65 uint8_t *pipe_session_key,
66 size_t pipe_session_key_len,
67 struct netr_SamInfo2 *sam2)
69 struct netr_SamInfo3 *info3;
71 info3 = copy_netr_SamInfo3(sam2, server_info->info3);
72 if (!info3) {
73 return NT_STATUS_NO_MEMORY;
76 if (server_info->user_session_key.length) {
77 memcpy(info3->base.key.key,
78 server_info->user_session_key.data,
79 MIN(sizeof(info3->base.key.key),
80 server_info->user_session_key.length));
81 if (pipe_session_key) {
82 arcfour_crypt(info3->base.key.key,
83 pipe_session_key, 16);
86 if (server_info->lm_session_key.length) {
87 memcpy(info3->base.LMSessKey.key,
88 server_info->lm_session_key.data,
89 MIN(sizeof(info3->base.LMSessKey.key),
90 server_info->lm_session_key.length));
91 if (pipe_session_key) {
92 arcfour_crypt(info3->base.LMSessKey.key,
93 pipe_session_key, 8);
97 sam2->base = info3->base;
99 return NT_STATUS_OK;
102 /****************************************************************************
103 inits a netr_SamInfo3 structure from an auth_serversupplied_info. sam3 must
104 already be initialized and is used as the talloc parent for its members.
105 *****************************************************************************/
107 NTSTATUS serverinfo_to_SamInfo3(struct auth_serversupplied_info *server_info,
108 uint8_t *pipe_session_key,
109 size_t pipe_session_key_len,
110 struct netr_SamInfo3 *sam3)
112 struct netr_SamInfo3 *info3;
114 info3 = copy_netr_SamInfo3(sam3, server_info->info3);
115 if (!info3) {
116 return NT_STATUS_NO_MEMORY;
119 if (server_info->user_session_key.length) {
120 memcpy(info3->base.key.key,
121 server_info->user_session_key.data,
122 MIN(sizeof(info3->base.key.key),
123 server_info->user_session_key.length));
124 if (pipe_session_key) {
125 arcfour_crypt(info3->base.key.key,
126 pipe_session_key, 16);
129 if (server_info->lm_session_key.length) {
130 memcpy(info3->base.LMSessKey.key,
131 server_info->lm_session_key.data,
132 MIN(sizeof(info3->base.LMSessKey.key),
133 server_info->lm_session_key.length));
134 if (pipe_session_key) {
135 arcfour_crypt(info3->base.LMSessKey.key,
136 pipe_session_key, 8);
140 sam3->base = info3->base;
142 sam3->sidcount = 0;
143 sam3->sids = NULL;
145 return NT_STATUS_OK;
148 /****************************************************************************
149 inits a netr_SamInfo6 structure from an auth_serversupplied_info. sam6 must
150 already be initialized and is used as the talloc parent for its members.
151 *****************************************************************************/
153 NTSTATUS serverinfo_to_SamInfo6(struct auth_serversupplied_info *server_info,
154 uint8_t *pipe_session_key,
155 size_t pipe_session_key_len,
156 struct netr_SamInfo6 *sam6)
158 struct pdb_domain_info *dominfo;
159 struct netr_SamInfo3 *info3;
161 if ((pdb_capabilities() & PDB_CAP_ADS) == 0) {
162 DEBUG(10,("Not adding validation info level 6 "
163 "without ADS passdb backend\n"));
164 return NT_STATUS_INVALID_INFO_CLASS;
167 dominfo = pdb_get_domain_info(sam6);
168 if (dominfo == NULL) {
169 return NT_STATUS_NO_MEMORY;
172 info3 = copy_netr_SamInfo3(sam6, server_info->info3);
173 if (!info3) {
174 return NT_STATUS_NO_MEMORY;
177 if (server_info->user_session_key.length) {
178 memcpy(info3->base.key.key,
179 server_info->user_session_key.data,
180 MIN(sizeof(info3->base.key.key),
181 server_info->user_session_key.length));
182 if (pipe_session_key) {
183 arcfour_crypt(info3->base.key.key,
184 pipe_session_key, 16);
187 if (server_info->lm_session_key.length) {
188 memcpy(info3->base.LMSessKey.key,
189 server_info->lm_session_key.data,
190 MIN(sizeof(info3->base.LMSessKey.key),
191 server_info->lm_session_key.length));
192 if (pipe_session_key) {
193 arcfour_crypt(info3->base.LMSessKey.key,
194 pipe_session_key, 8);
198 sam6->base = info3->base;
200 sam6->sidcount = 0;
201 sam6->sids = NULL;
203 sam6->dns_domainname.string = talloc_strdup(sam6, dominfo->dns_domain);
204 if (sam6->dns_domainname.string == NULL) {
205 return NT_STATUS_NO_MEMORY;
208 sam6->principle.string = talloc_asprintf(sam6, "%s@%s",
209 sam6->base.account_name.string,
210 sam6->dns_domainname.string);
211 if (sam6->principle.string == NULL) {
212 return NT_STATUS_NO_MEMORY;
215 return NT_STATUS_OK;
218 static NTSTATUS sids_to_samr_RidWithAttributeArray(
219 TALLOC_CTX *mem_ctx,
220 struct samr_RidWithAttributeArray *groups,
221 const struct dom_sid *domain_sid,
222 const struct dom_sid *sids,
223 size_t num_sids)
225 unsigned int i;
226 bool ok;
228 groups->rids = talloc_array(mem_ctx,
229 struct samr_RidWithAttribute, num_sids);
230 if (!groups->rids) {
231 return NT_STATUS_NO_MEMORY;
234 for (i = 0; i < num_sids; i++) {
235 ok = sid_peek_check_rid(domain_sid, &sids[i],
236 &groups->rids[i].rid);
237 if (!ok) continue;
239 groups->rids[i].attributes = SE_GROUP_MANDATORY |
240 SE_GROUP_ENABLED_BY_DEFAULT |
241 SE_GROUP_ENABLED;
242 groups->count++;
245 return NT_STATUS_OK;
249 #define RET_NOMEM(ptr) do { \
250 if (!ptr) { \
251 TALLOC_FREE(info3); \
252 return NT_STATUS_NO_MEMORY; \
253 } } while(0)
255 NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx,
256 struct samu *samu,
257 const char *login_server,
258 struct netr_SamInfo3 **_info3)
260 struct netr_SamInfo3 *info3;
261 const struct dom_sid *user_sid;
262 const struct dom_sid *group_sid;
263 struct dom_sid domain_sid;
264 struct dom_sid *group_sids;
265 size_t num_group_sids;
266 const char *tmp;
267 gid_t *gids;
268 NTSTATUS status;
269 bool ok;
271 user_sid = pdb_get_user_sid(samu);
272 group_sid = pdb_get_group_sid(samu);
274 if (!user_sid || !group_sid) {
275 DEBUG(1, ("Sam account is missing sids!\n"));
276 return NT_STATUS_UNSUCCESSFUL;
279 info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
280 if (!info3) {
281 return NT_STATUS_NO_MEMORY;
284 unix_to_nt_time(&info3->base.last_logon, pdb_get_logon_time(samu));
285 unix_to_nt_time(&info3->base.last_logoff, get_time_t_max());
286 unix_to_nt_time(&info3->base.acct_expiry, get_time_t_max());
287 unix_to_nt_time(&info3->base.last_password_change,
288 pdb_get_pass_last_set_time(samu));
289 unix_to_nt_time(&info3->base.allow_password_change,
290 pdb_get_pass_can_change_time(samu));
291 unix_to_nt_time(&info3->base.force_password_change,
292 pdb_get_pass_must_change_time(samu));
294 tmp = pdb_get_username(samu);
295 if (tmp) {
296 info3->base.account_name.string = talloc_strdup(info3, tmp);
297 RET_NOMEM(info3->base.account_name.string);
299 tmp = pdb_get_fullname(samu);
300 if (tmp) {
301 info3->base.full_name.string = talloc_strdup(info3, tmp);
302 RET_NOMEM(info3->base.full_name.string);
304 tmp = pdb_get_logon_script(samu);
305 if (tmp) {
306 info3->base.logon_script.string = talloc_strdup(info3, tmp);
307 RET_NOMEM(info3->base.logon_script.string);
309 if (tmp) {
310 info3->base.profile_path.string = talloc_strdup(info3, tmp);
311 RET_NOMEM(info3->base.profile_path.string);
313 if (tmp) {
314 info3->base.home_directory.string = talloc_strdup(info3, tmp);
315 RET_NOMEM(info3->base.home_directory.string);
317 if (tmp) {
318 info3->base.home_drive.string = talloc_strdup(info3, tmp);
319 RET_NOMEM(info3->base.home_drive.string);
322 info3->base.logon_count = pdb_get_logon_count(samu);
323 info3->base.bad_password_count = pdb_get_bad_password_count(samu);
325 sid_copy(&domain_sid, user_sid);
326 sid_split_rid(&domain_sid, &info3->base.rid);
328 ok = sid_peek_check_rid(&domain_sid, group_sid,
329 &info3->base.primary_gid);
330 if (!ok) {
331 DEBUG(1, ("The primary group sid domain does not"
332 "match user sid domain for user: %s\n",
333 pdb_get_username(samu)));
334 TALLOC_FREE(info3);
335 return NT_STATUS_UNSUCCESSFUL;
338 status = pdb_enum_group_memberships(mem_ctx, samu,
339 &group_sids, &gids,
340 &num_group_sids);
341 if (!NT_STATUS_IS_OK(status)) {
342 DEBUG(1, ("Failed to get groups from sam account.\n"));
343 TALLOC_FREE(info3);
344 return status;
347 status = sids_to_samr_RidWithAttributeArray(info3,
348 &info3->base.groups,
349 &domain_sid,
350 group_sids,
351 num_group_sids);
352 if (!NT_STATUS_IS_OK(status)) {
353 TALLOC_FREE(info3);
354 return status;
357 /* We don't need sids and gids after the conversion */
358 TALLOC_FREE(group_sids);
359 TALLOC_FREE(gids);
360 num_group_sids = 0;
362 /* FIXME: should we add other flags ? */
363 info3->base.user_flags = NETLOGON_EXTRA_SIDS;
365 if (login_server) {
366 info3->base.logon_server.string = talloc_strdup(info3, login_server);
367 RET_NOMEM(info3->base.logon_server.string);
370 info3->base.domain.string = talloc_strdup(info3,
371 pdb_get_domain(samu));
372 RET_NOMEM(info3->base.domain.string);
374 info3->base.domain_sid = sid_dup_talloc(info3, &domain_sid);
375 RET_NOMEM(info3->base.domain_sid);
377 info3->base.acct_flags = pdb_get_acct_ctrl(samu);
379 *_info3 = info3;
380 return NT_STATUS_OK;
383 #undef RET_NOMEM
385 #define RET_NOMEM(ptr) do { \
386 if (!ptr) { \
387 TALLOC_FREE(info3); \
388 return NULL; \
389 } } while(0)
391 struct netr_SamInfo3 *copy_netr_SamInfo3(TALLOC_CTX *mem_ctx,
392 struct netr_SamInfo3 *orig)
394 struct netr_SamInfo3 *info3;
395 unsigned int i;
397 info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
398 if (!info3) return NULL;
400 /* first copy all, then realloc pointers */
401 info3->base = orig->base;
403 if (orig->base.account_name.string) {
404 info3->base.account_name.string =
405 talloc_strdup(info3, orig->base.account_name.string);
406 RET_NOMEM(info3->base.account_name.string);
408 if (orig->base.full_name.string) {
409 info3->base.full_name.string =
410 talloc_strdup(info3, orig->base.full_name.string);
411 RET_NOMEM(info3->base.full_name.string);
413 if (orig->base.logon_script.string) {
414 info3->base.logon_script.string =
415 talloc_strdup(info3, orig->base.logon_script.string);
416 RET_NOMEM(info3->base.logon_script.string);
418 if (orig->base.profile_path.string) {
419 info3->base.profile_path.string =
420 talloc_strdup(info3, orig->base.profile_path.string);
421 RET_NOMEM(info3->base.profile_path.string);
423 if (orig->base.home_directory.string) {
424 info3->base.home_directory.string =
425 talloc_strdup(info3, orig->base.home_directory.string);
426 RET_NOMEM(info3->base.home_directory.string);
428 if (orig->base.home_drive.string) {
429 info3->base.home_drive.string =
430 talloc_strdup(info3, orig->base.home_drive.string);
431 RET_NOMEM(info3->base.home_drive.string);
434 if (orig->base.groups.count) {
435 info3->base.groups.rids = (struct samr_RidWithAttribute *)
436 talloc_memdup(info3, orig->base.groups.rids,
437 (sizeof(struct samr_RidWithAttribute) *
438 orig->base.groups.count));
439 RET_NOMEM(info3->base.groups.rids);
442 if (orig->base.logon_server.string) {
443 info3->base.logon_server.string =
444 talloc_strdup(info3, orig->base.logon_server.string);
445 RET_NOMEM(info3->base.logon_server.string);
447 if (orig->base.domain.string) {
448 info3->base.domain.string =
449 talloc_strdup(info3, orig->base.domain.string);
450 RET_NOMEM(info3->base.domain.string);
453 if (orig->base.domain_sid) {
454 info3->base.domain_sid = sid_dup_talloc(info3, orig->base.domain_sid);
455 RET_NOMEM(info3->base.domain_sid);
458 if (orig->sidcount) {
459 info3->sids = talloc_array(info3, struct netr_SidAttr,
460 orig->sidcount);
461 RET_NOMEM(info3->sids);
462 for (i = 0; i < orig->sidcount; i++) {
463 info3->sids[i].sid = sid_dup_talloc(info3->sids,
464 orig->sids[i].sid);
465 RET_NOMEM(info3->sids[i].sid);
469 return info3;
472 static NTSTATUS wbcsids_to_samr_RidWithAttributeArray(
473 TALLOC_CTX *mem_ctx,
474 struct samr_RidWithAttributeArray *groups,
475 const struct dom_sid *domain_sid,
476 const struct wbcSidWithAttr *sids,
477 size_t num_sids)
479 unsigned int i;
480 bool ok;
482 groups->rids = talloc_array(mem_ctx,
483 struct samr_RidWithAttribute, num_sids);
484 if (!groups->rids) {
485 return NT_STATUS_NO_MEMORY;
488 /* a wbcDomainSid is the same as a dom_sid */
489 for (i = 0; i < num_sids; i++) {
490 ok = sid_peek_check_rid(domain_sid,
491 (const struct dom_sid *)&sids[i].sid,
492 &groups->rids[i].rid);
493 if (!ok) continue;
495 groups->rids[i].attributes = SE_GROUP_MANDATORY |
496 SE_GROUP_ENABLED_BY_DEFAULT |
497 SE_GROUP_ENABLED;
498 groups->count++;
501 return NT_STATUS_OK;
504 struct netr_SamInfo3 *wbcAuthUserInfo_to_netr_SamInfo3(TALLOC_CTX *mem_ctx,
505 const struct wbcAuthUserInfo *info)
507 struct netr_SamInfo3 *info3;
508 struct dom_sid user_sid;
509 struct dom_sid group_sid;
510 struct dom_sid domain_sid;
511 NTSTATUS status;
512 bool ok;
514 memcpy(&user_sid, &info->sids[0].sid, sizeof(user_sid));
515 memcpy(&group_sid, &info->sids[1].sid, sizeof(group_sid));
517 info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
518 if (!info3) return NULL;
520 info3->base.last_logon = info->logon_time;
521 info3->base.last_logoff = info->logoff_time;
522 info3->base.acct_expiry = info->kickoff_time;
523 info3->base.last_password_change = info->pass_last_set_time;
524 info3->base.allow_password_change = info->pass_can_change_time;
525 info3->base.force_password_change = info->pass_must_change_time;
527 if (info->account_name) {
528 info3->base.account_name.string =
529 talloc_strdup(info3, info->account_name);
530 RET_NOMEM(info3->base.account_name.string);
532 if (info->full_name) {
533 info3->base.full_name.string =
534 talloc_strdup(info3, info->full_name);
535 RET_NOMEM(info3->base.full_name.string);
537 if (info->logon_script) {
538 info3->base.logon_script.string =
539 talloc_strdup(info3, info->logon_script);
540 RET_NOMEM(info3->base.logon_script.string);
542 if (info->profile_path) {
543 info3->base.profile_path.string =
544 talloc_strdup(info3, info->profile_path);
545 RET_NOMEM(info3->base.profile_path.string);
547 if (info->home_directory) {
548 info3->base.home_directory.string =
549 talloc_strdup(info3, info->home_directory);
550 RET_NOMEM(info3->base.home_directory.string);
552 if (info->home_drive) {
553 info3->base.home_drive.string =
554 talloc_strdup(info3, info->home_drive);
555 RET_NOMEM(info3->base.home_drive.string);
558 info3->base.logon_count = info->logon_count;
559 info3->base.bad_password_count = info->bad_password_count;
561 sid_copy(&domain_sid, &user_sid);
562 sid_split_rid(&domain_sid, &info3->base.rid);
564 ok = sid_peek_check_rid(&domain_sid, &group_sid,
565 &info3->base.primary_gid);
566 if (!ok) {
567 DEBUG(1, ("The primary group sid domain does not"
568 "match user sid domain for user: %s\n",
569 info->account_name));
570 TALLOC_FREE(info3);
571 return NULL;
574 status = wbcsids_to_samr_RidWithAttributeArray(info3,
575 &info3->base.groups,
576 &domain_sid,
577 &info->sids[1],
578 info->num_sids - 1);
579 if (!NT_STATUS_IS_OK(status)) {
580 TALLOC_FREE(info3);
581 return NULL;
584 info3->base.user_flags = info->user_flags;
585 memcpy(info3->base.key.key, info->user_session_key, 16);
587 if (info->logon_server) {
588 info3->base.logon_server.string =
589 talloc_strdup(info3, info->logon_server);
590 RET_NOMEM(info3->base.logon_server.string);
592 if (info->domain_name) {
593 info3->base.domain.string =
594 talloc_strdup(info3, info->domain_name);
595 RET_NOMEM(info3->base.domain.string);
598 info3->base.domain_sid = sid_dup_talloc(info3, &domain_sid);
599 RET_NOMEM(info3->base.domain_sid);
601 memcpy(info3->base.LMSessKey.key, info->lm_session_key, 8);
602 info3->base.acct_flags = info->acct_flags;
604 return info3;