s3: Attempt to fix the build without kerberos
[Samba/gebeck_regimport.git] / source3 / passdb / lookup_sid.c
blob3f7be2a0de8de6f779ca9b377b3537e00d0a96de
1 /*
2 Unix SMB/CIFS implementation.
3 uid/user handling
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Gerald (Jerry) Carter 2003
6 Copyright (C) Volker Lendecke 2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "passdb.h"
24 #include "../librpc/gen_ndr/ndr_security.h"
25 #include "secrets.h"
26 #include "memcache.h"
27 #include "idmap_cache.h"
28 #include "../libcli/security/security.h"
29 #include "lib/winbind_util.h"
31 /*****************************************************************
32 Dissect a user-provided name into domain, name, sid and type.
34 If an explicit domain name was given in the form domain\user, it
35 has to try that. If no explicit domain name was given, we have
36 to do guesswork.
37 *****************************************************************/
39 bool lookup_name(TALLOC_CTX *mem_ctx,
40 const char *full_name, int flags,
41 const char **ret_domain, const char **ret_name,
42 struct dom_sid *ret_sid, enum lsa_SidType *ret_type)
44 char *p;
45 const char *tmp;
46 const char *domain = NULL;
47 const char *name = NULL;
48 uint32 rid;
49 struct dom_sid sid;
50 enum lsa_SidType type;
51 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
53 if (tmp_ctx == NULL) {
54 DEBUG(0, ("talloc_new failed\n"));
55 return false;
58 p = strchr_m(full_name, '\\');
60 if (p != NULL) {
61 domain = talloc_strndup(tmp_ctx, full_name,
62 PTR_DIFF(p, full_name));
63 name = talloc_strdup(tmp_ctx, p+1);
64 } else {
65 domain = talloc_strdup(tmp_ctx, "");
66 name = talloc_strdup(tmp_ctx, full_name);
69 if ((domain == NULL) || (name == NULL)) {
70 DEBUG(0, ("talloc failed\n"));
71 TALLOC_FREE(tmp_ctx);
72 return false;
75 DEBUG(10,("lookup_name: %s => domain=[%s], name=[%s]\n",
76 full_name, domain, name));
77 DEBUG(10, ("lookup_name: flags = 0x0%x\n", flags));
79 if ((flags & LOOKUP_NAME_DOMAIN) &&
80 strequal(domain, get_global_sam_name()))
83 /* It's our own domain, lookup the name in passdb */
84 if (lookup_global_sam_name(name, flags, &rid, &type)) {
85 sid_compose(&sid, get_global_sam_sid(), rid);
86 goto ok;
88 TALLOC_FREE(tmp_ctx);
89 return false;
92 if ((flags & LOOKUP_NAME_BUILTIN) &&
93 strequal(domain, builtin_domain_name()))
95 if (strlen(name) == 0) {
96 /* Swap domain and name */
97 tmp = name; name = domain; domain = tmp;
98 sid_copy(&sid, &global_sid_Builtin);
99 type = SID_NAME_DOMAIN;
100 goto ok;
103 /* Explicit request for a name in BUILTIN */
104 if (lookup_builtin_name(name, &rid)) {
105 sid_compose(&sid, &global_sid_Builtin, rid);
106 type = SID_NAME_ALIAS;
107 goto ok;
109 TALLOC_FREE(tmp_ctx);
110 return false;
113 /* Try the explicit winbind lookup first, don't let it guess the
114 * domain yet at this point yet. This comes later. */
116 if ((domain[0] != '\0') &&
117 (flags & ~(LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED)) &&
118 (winbind_lookup_name(domain, name, &sid, &type))) {
119 goto ok;
122 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
123 && strequal(domain, unix_users_domain_name())) {
124 if (lookup_unix_user_name(name, &sid)) {
125 type = SID_NAME_USER;
126 goto ok;
128 TALLOC_FREE(tmp_ctx);
129 return false;
132 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
133 && strequal(domain, unix_groups_domain_name())) {
134 if (lookup_unix_group_name(name, &sid)) {
135 type = SID_NAME_DOM_GRP;
136 goto ok;
138 TALLOC_FREE(tmp_ctx);
139 return false;
142 if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
143 TALLOC_FREE(tmp_ctx);
144 return false;
147 /* Now the guesswork begins, we haven't been given an explicit
148 * domain. Try the sequence as documented on
149 * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
150 * November 27, 2005 */
152 /* 1. well-known names */
154 if ((flags & LOOKUP_NAME_WKN) &&
155 lookup_wellknown_name(tmp_ctx, name, &sid, &domain))
157 type = SID_NAME_WKN_GRP;
158 goto ok;
161 /* 2. Builtin domain as such */
163 if ((flags & (LOOKUP_NAME_BUILTIN|LOOKUP_NAME_REMOTE)) &&
164 strequal(name, builtin_domain_name()))
166 /* Swap domain and name */
167 tmp = name; name = domain; domain = tmp;
168 sid_copy(&sid, &global_sid_Builtin);
169 type = SID_NAME_DOMAIN;
170 goto ok;
173 /* 3. Account domain */
175 if ((flags & LOOKUP_NAME_DOMAIN) &&
176 strequal(name, get_global_sam_name()))
178 if (!secrets_fetch_domain_sid(name, &sid)) {
179 DEBUG(3, ("Could not fetch my SID\n"));
180 TALLOC_FREE(tmp_ctx);
181 return false;
183 /* Swap domain and name */
184 tmp = name; name = domain; domain = tmp;
185 type = SID_NAME_DOMAIN;
186 goto ok;
189 /* 4. Primary domain */
191 if ((flags & LOOKUP_NAME_DOMAIN) && !IS_DC &&
192 strequal(name, lp_workgroup()))
194 if (!secrets_fetch_domain_sid(name, &sid)) {
195 DEBUG(3, ("Could not fetch the domain SID\n"));
196 TALLOC_FREE(tmp_ctx);
197 return false;
199 /* Swap domain and name */
200 tmp = name; name = domain; domain = tmp;
201 type = SID_NAME_DOMAIN;
202 goto ok;
205 /* 5. Trusted domains as such, to me it looks as if members don't do
206 this, tested an XP workstation in a NT domain -- vl */
208 if ((flags & LOOKUP_NAME_REMOTE) && IS_DC &&
209 (pdb_get_trusteddom_pw(name, NULL, &sid, NULL)))
211 /* Swap domain and name */
212 tmp = name; name = domain; domain = tmp;
213 type = SID_NAME_DOMAIN;
214 goto ok;
217 /* 6. Builtin aliases */
219 if ((flags & LOOKUP_NAME_BUILTIN) &&
220 lookup_builtin_name(name, &rid))
222 domain = talloc_strdup(tmp_ctx, builtin_domain_name());
223 sid_compose(&sid, &global_sid_Builtin, rid);
224 type = SID_NAME_ALIAS;
225 goto ok;
228 /* 7. Local systems' SAM (DCs don't have a local SAM) */
229 /* 8. Primary SAM (On members, this is the domain) */
231 /* Both cases are done by looking at our passdb */
233 if ((flags & LOOKUP_NAME_DOMAIN) &&
234 lookup_global_sam_name(name, flags, &rid, &type))
236 domain = talloc_strdup(tmp_ctx, get_global_sam_name());
237 sid_compose(&sid, get_global_sam_sid(), rid);
238 goto ok;
241 /* Now our local possibilities are exhausted. */
243 if (!(flags & LOOKUP_NAME_REMOTE)) {
244 TALLOC_FREE(tmp_ctx);
245 return false;
248 /* If we are not a DC, we have to ask in our primary domain. Let
249 * winbind do that. */
251 if (!IS_DC &&
252 (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
253 domain = talloc_strdup(tmp_ctx, lp_workgroup());
254 goto ok;
257 /* 9. Trusted domains */
259 /* If we're a DC we have to ask all trusted DC's. Winbind does not do
260 * that (yet), but give it a chance. */
262 if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
263 struct dom_sid dom_sid;
264 enum lsa_SidType domain_type;
266 if (type == SID_NAME_DOMAIN) {
267 /* Swap name and type */
268 tmp = name; name = domain; domain = tmp;
269 goto ok;
272 /* Here we have to cope with a little deficiency in the
273 * winbind API: We have to ask it again for the name of the
274 * domain it figured out itself. Maybe fix that later... */
276 sid_copy(&dom_sid, &sid);
277 sid_split_rid(&dom_sid, NULL);
279 if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
280 &domain_type) ||
281 (domain_type != SID_NAME_DOMAIN)) {
282 DEBUG(2, ("winbind could not find the domain's name "
283 "it just looked up for us\n"));
284 TALLOC_FREE(tmp_ctx);
285 return false;
287 goto ok;
290 /* 10. Don't translate */
292 /* 11. Ok, windows would end here. Samba has two more options:
293 Unmapped users and unmapped groups */
295 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
296 && lookup_unix_user_name(name, &sid)) {
297 domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
298 type = SID_NAME_USER;
299 goto ok;
302 if (((flags & LOOKUP_NAME_NO_NSS) == 0)
303 && lookup_unix_group_name(name, &sid)) {
304 domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
305 type = SID_NAME_DOM_GRP;
306 goto ok;
310 * Ok, all possibilities tried. Fail.
313 TALLOC_FREE(tmp_ctx);
314 return false;
317 if ((domain == NULL) || (name == NULL)) {
318 DEBUG(0, ("talloc failed\n"));
319 TALLOC_FREE(tmp_ctx);
320 return false;
324 * Hand over the results to the talloc context we've been given.
327 if ((ret_name != NULL) &&
328 !(*ret_name = talloc_strdup(mem_ctx, name))) {
329 DEBUG(0, ("talloc failed\n"));
330 TALLOC_FREE(tmp_ctx);
331 return false;
334 if (ret_domain != NULL) {
335 char *tmp_dom;
336 if (!(tmp_dom = talloc_strdup(mem_ctx, domain))) {
337 DEBUG(0, ("talloc failed\n"));
338 TALLOC_FREE(tmp_ctx);
339 return false;
341 strupper_m(tmp_dom);
342 *ret_domain = tmp_dom;
345 if (ret_sid != NULL) {
346 sid_copy(ret_sid, &sid);
349 if (ret_type != NULL) {
350 *ret_type = type;
353 TALLOC_FREE(tmp_ctx);
354 return true;
357 /************************************************************************
358 Names from smb.conf can be unqualified. eg. valid users = foo
359 These names should never map to a remote name. Try global_sam_name()\foo,
360 and then "Unix Users"\foo (or "Unix Groups"\foo).
361 ************************************************************************/
363 bool lookup_name_smbconf(TALLOC_CTX *mem_ctx,
364 const char *full_name, int flags,
365 const char **ret_domain, const char **ret_name,
366 struct dom_sid *ret_sid, enum lsa_SidType *ret_type)
368 char *qualified_name;
369 const char *p;
371 /* NB. No winbindd_separator here as lookup_name needs \\' */
372 if ((p = strchr_m(full_name, *lp_winbind_separator())) != NULL) {
374 /* The name is already qualified with a domain. */
376 if (*lp_winbind_separator() != '\\') {
377 char *tmp;
379 /* lookup_name() needs '\\' as a separator */
381 tmp = talloc_strdup(mem_ctx, full_name);
382 if (!tmp) {
383 return false;
385 tmp[p - full_name] = '\\';
386 full_name = tmp;
389 return lookup_name(mem_ctx, full_name, flags,
390 ret_domain, ret_name,
391 ret_sid, ret_type);
394 /* Try with our own SAM name. */
395 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
396 get_global_sam_name(),
397 full_name );
398 if (!qualified_name) {
399 return false;
402 if (lookup_name(mem_ctx, qualified_name, flags,
403 ret_domain, ret_name,
404 ret_sid, ret_type)) {
405 return true;
408 /* Finally try with "Unix Users" or "Unix Group" */
409 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
410 flags & LOOKUP_NAME_GROUP ?
411 unix_groups_domain_name() :
412 unix_users_domain_name(),
413 full_name );
414 if (!qualified_name) {
415 return false;
418 return lookup_name(mem_ctx, qualified_name, flags,
419 ret_domain, ret_name,
420 ret_sid, ret_type);
423 static bool wb_lookup_rids(TALLOC_CTX *mem_ctx,
424 const struct dom_sid *domain_sid,
425 int num_rids, uint32 *rids,
426 const char **domain_name,
427 const char **names, enum lsa_SidType *types)
429 int i;
430 const char **my_names;
431 enum lsa_SidType *my_types;
432 TALLOC_CTX *tmp_ctx;
434 if (!(tmp_ctx = talloc_init("wb_lookup_rids"))) {
435 return false;
438 if (!winbind_lookup_rids(tmp_ctx, domain_sid, num_rids, rids,
439 domain_name, &my_names, &my_types)) {
440 *domain_name = "";
441 for (i=0; i<num_rids; i++) {
442 names[i] = "";
443 types[i] = SID_NAME_UNKNOWN;
445 TALLOC_FREE(tmp_ctx);
446 return true;
449 if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
450 TALLOC_FREE(tmp_ctx);
451 return false;
455 * winbind_lookup_rids allocates its own array. We've been given the
456 * array, so copy it over
459 for (i=0; i<num_rids; i++) {
460 if (my_names[i] == NULL) {
461 TALLOC_FREE(tmp_ctx);
462 return false;
464 if (!(names[i] = talloc_strdup(names, my_names[i]))) {
465 TALLOC_FREE(tmp_ctx);
466 return false;
468 types[i] = my_types[i];
470 TALLOC_FREE(tmp_ctx);
471 return true;
474 static bool lookup_rids(TALLOC_CTX *mem_ctx, const struct dom_sid *domain_sid,
475 int num_rids, uint32_t *rids,
476 const char **domain_name,
477 const char ***names, enum lsa_SidType **types)
479 int i;
481 DEBUG(10, ("lookup_rids called for domain sid '%s'\n",
482 sid_string_dbg(domain_sid)));
484 if (num_rids) {
485 *names = talloc_zero_array(mem_ctx, const char *, num_rids);
486 *types = talloc_array(mem_ctx, enum lsa_SidType, num_rids);
488 if ((*names == NULL) || (*types == NULL)) {
489 return false;
492 for (i = 0; i < num_rids; i++)
493 (*types)[i] = SID_NAME_UNKNOWN;
494 } else {
495 *names = NULL;
496 *types = NULL;
499 if (sid_check_is_domain(domain_sid)) {
500 NTSTATUS result;
502 if (*domain_name == NULL) {
503 *domain_name = talloc_strdup(
504 mem_ctx, get_global_sam_name());
507 if (*domain_name == NULL) {
508 return false;
511 become_root();
512 result = pdb_lookup_rids(domain_sid, num_rids, rids,
513 *names, *types);
514 unbecome_root();
516 return (NT_STATUS_IS_OK(result) ||
517 NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
518 NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
521 if (sid_check_is_builtin(domain_sid)) {
523 if (*domain_name == NULL) {
524 *domain_name = talloc_strdup(
525 mem_ctx, builtin_domain_name());
528 if (*domain_name == NULL) {
529 return false;
532 for (i=0; i<num_rids; i++) {
533 if (lookup_builtin_rid(*names, rids[i],
534 &(*names)[i])) {
535 if ((*names)[i] == NULL) {
536 return false;
538 (*types)[i] = SID_NAME_ALIAS;
539 } else {
540 (*types)[i] = SID_NAME_UNKNOWN;
543 return true;
546 if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
547 for (i=0; i<num_rids; i++) {
548 struct dom_sid sid;
549 sid_compose(&sid, domain_sid, rids[i]);
550 if (lookup_wellknown_sid(mem_ctx, &sid,
551 domain_name, &(*names)[i])) {
552 if ((*names)[i] == NULL) {
553 return false;
555 (*types)[i] = SID_NAME_WKN_GRP;
556 } else {
557 (*types)[i] = SID_NAME_UNKNOWN;
560 return true;
563 if (sid_check_is_unix_users(domain_sid)) {
564 if (*domain_name == NULL) {
565 *domain_name = talloc_strdup(
566 mem_ctx, unix_users_domain_name());
567 if (*domain_name == NULL) {
568 return false;
571 for (i=0; i<num_rids; i++) {
572 (*names)[i] = talloc_strdup(
573 (*names), uidtoname(rids[i]));
574 if ((*names)[i] == NULL) {
575 return false;
577 (*types)[i] = SID_NAME_USER;
579 return true;
582 if (sid_check_is_unix_groups(domain_sid)) {
583 if (*domain_name == NULL) {
584 *domain_name = talloc_strdup(
585 mem_ctx, unix_groups_domain_name());
586 if (*domain_name == NULL) {
587 return false;
590 for (i=0; i<num_rids; i++) {
591 (*names)[i] = talloc_strdup(
592 (*names), gidtoname(rids[i]));
593 if ((*names)[i] == NULL) {
594 return false;
596 (*types)[i] = SID_NAME_DOM_GRP;
598 return true;
601 return wb_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
602 domain_name, *names, *types);
606 * Is the SID a domain as such? If yes, lookup its name.
609 static bool lookup_as_domain(const struct dom_sid *sid, TALLOC_CTX *mem_ctx,
610 const char **name)
612 const char *tmp;
613 enum lsa_SidType type;
615 if (sid_check_is_domain(sid)) {
616 *name = talloc_strdup(mem_ctx, get_global_sam_name());
617 return true;
620 if (sid_check_is_builtin(sid)) {
621 *name = talloc_strdup(mem_ctx, builtin_domain_name());
622 return true;
625 if (sid_check_is_wellknown_domain(sid, &tmp)) {
626 *name = talloc_strdup(mem_ctx, tmp);
627 return true;
630 if (sid_check_is_unix_users(sid)) {
631 *name = talloc_strdup(mem_ctx, unix_users_domain_name());
632 return true;
635 if (sid_check_is_unix_groups(sid)) {
636 *name = talloc_strdup(mem_ctx, unix_groups_domain_name());
637 return true;
640 if (sid->num_auths != 4) {
641 /* This can't be a domain */
642 return false;
645 if (IS_DC) {
646 uint32 i, num_domains;
647 struct trustdom_info **domains;
649 /* This is relatively expensive, but it happens only on DCs
650 * and for SIDs that have 4 sub-authorities and thus look like
651 * domains */
653 if (!NT_STATUS_IS_OK(pdb_enum_trusteddoms(mem_ctx,
654 &num_domains,
655 &domains))) {
656 return false;
659 for (i=0; i<num_domains; i++) {
660 if (dom_sid_equal(sid, &domains[i]->sid)) {
661 *name = talloc_strdup(mem_ctx,
662 domains[i]->name);
663 return true;
666 return false;
669 if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
670 (type == SID_NAME_DOMAIN)) {
671 *name = tmp;
672 return true;
675 return false;
679 * This tries to implement the rather weird rules for the lsa_lookup level
680 * parameter.
682 * This is as close as we can get to what W2k3 does. With this we survive the
683 * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
684 * different, but I assume that's just being too liberal. For example, W2k3
685 * replies to everything else but the levels 1-6 with INVALID_PARAMETER
686 * whereas NT4 does the same as level 1 (I think). I did not fully test that
687 * with NT4, this is what w2k3 does.
689 * Level 1: Ask everywhere
690 * Level 2: Ask domain and trusted domains, no builtin and wkn
691 * Level 3: Only ask domain
692 * Level 4: W2k3ad: Only ask AD trusts
693 * Level 5: Only ask transitive forest trusts
694 * Level 6: Like 4
697 static bool check_dom_sid_to_level(const struct dom_sid *sid, int level)
699 int ret = false;
701 switch(level) {
702 case 1:
703 ret = true;
704 break;
705 case 2:
706 ret = (!sid_check_is_builtin(sid) &&
707 !sid_check_is_wellknown_domain(sid, NULL));
708 break;
709 case 3:
710 case 4:
711 case 6:
712 ret = sid_check_is_domain(sid);
713 break;
714 case 5:
715 ret = false;
716 break;
719 DEBUG(10, ("%s SID %s in level %d\n",
720 ret ? "Accepting" : "Rejecting",
721 sid_string_dbg(sid), level));
722 return ret;
726 * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
727 * references to domains, it is explicitly made for this.
729 * This attempts to be as efficient as possible: It collects all SIDs
730 * belonging to a domain and hands them in bulk to the appropriate lookup
731 * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
732 * *hugely* from this.
735 NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
736 const struct dom_sid **sids, int level,
737 struct lsa_dom_info **ret_domains,
738 struct lsa_name_info **ret_names)
740 TALLOC_CTX *tmp_ctx;
741 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
742 struct lsa_name_info *name_infos;
743 struct lsa_dom_info *dom_infos = NULL;
745 int i, j;
747 if (!(tmp_ctx = talloc_new(mem_ctx))) {
748 DEBUG(0, ("talloc_new failed\n"));
749 return NT_STATUS_NO_MEMORY;
752 if (num_sids) {
753 name_infos = talloc_array(mem_ctx, struct lsa_name_info, num_sids);
754 if (name_infos == NULL) {
755 result = NT_STATUS_NO_MEMORY;
756 goto fail;
758 } else {
759 name_infos = NULL;
762 dom_infos = talloc_zero_array(mem_ctx, struct lsa_dom_info,
763 LSA_REF_DOMAIN_LIST_MULTIPLIER);
764 if (dom_infos == NULL) {
765 result = NT_STATUS_NO_MEMORY;
766 goto fail;
769 /* First build up the data structures:
771 * dom_infos is a list of domains referenced in the list of
772 * SIDs. Later we will walk the list of domains and look up the RIDs
773 * in bulk.
775 * name_infos is a shadow-copy of the SIDs array to collect the real
776 * data.
778 * dom_info->idxs is an index into the name_infos array. The
779 * difficulty we have here is that we need to keep the SIDs the client
780 * asked for in the same order for the reply
783 for (i=0; i<num_sids; i++) {
784 struct dom_sid sid;
785 uint32_t rid = 0;
786 const char *domain_name = NULL;
788 sid_copy(&sid, sids[i]);
789 name_infos[i].type = SID_NAME_USE_NONE;
791 if (lookup_as_domain(&sid, name_infos, &domain_name)) {
792 /* We can't push that through the normal lookup
793 * process, as this would reference illegal
794 * domains.
796 * For example S-1-5-32 would end up referencing
797 * domain S-1-5- with RID 32 which is clearly wrong.
799 if (domain_name == NULL) {
800 result = NT_STATUS_NO_MEMORY;
801 goto fail;
804 name_infos[i].rid = 0;
805 name_infos[i].type = SID_NAME_DOMAIN;
806 name_infos[i].name = NULL;
808 if (sid_check_is_builtin(&sid)) {
809 /* Yes, W2k3 returns "BUILTIN" both as domain
810 * and name here */
811 name_infos[i].name = talloc_strdup(
812 name_infos, builtin_domain_name());
813 if (name_infos[i].name == NULL) {
814 result = NT_STATUS_NO_MEMORY;
815 goto fail;
818 } else {
819 /* This is a normal SID with rid component */
820 if (!sid_split_rid(&sid, &rid)) {
821 result = NT_STATUS_INVALID_SID;
822 goto fail;
826 if (!check_dom_sid_to_level(&sid, level)) {
827 name_infos[i].rid = 0;
828 name_infos[i].type = SID_NAME_UNKNOWN;
829 name_infos[i].name = NULL;
830 continue;
833 for (j=0; j<LSA_REF_DOMAIN_LIST_MULTIPLIER; j++) {
834 if (!dom_infos[j].valid) {
835 break;
837 if (dom_sid_equal(&sid, &dom_infos[j].sid)) {
838 break;
842 if (j == LSA_REF_DOMAIN_LIST_MULTIPLIER) {
843 /* TODO: What's the right error message here? */
844 result = NT_STATUS_NONE_MAPPED;
845 goto fail;
848 if (!dom_infos[j].valid) {
849 /* We found a domain not yet referenced, create a new
850 * ref. */
851 dom_infos[j].valid = true;
852 sid_copy(&dom_infos[j].sid, &sid);
854 if (domain_name != NULL) {
855 /* This name was being found above in the case
856 * when we found a domain SID */
857 dom_infos[j].name =
858 talloc_strdup(dom_infos, domain_name);
859 if (dom_infos[j].name == NULL) {
860 result = NT_STATUS_NO_MEMORY;
861 goto fail;
863 } else {
864 /* lookup_rids will take care of this */
865 dom_infos[j].name = NULL;
869 name_infos[i].dom_idx = j;
871 if (name_infos[i].type == SID_NAME_USE_NONE) {
872 name_infos[i].rid = rid;
874 ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
875 &dom_infos[j].num_idxs);
877 if (dom_infos[j].idxs == NULL) {
878 result = NT_STATUS_NO_MEMORY;
879 goto fail;
884 /* Iterate over the domains found */
886 for (i=0; i<LSA_REF_DOMAIN_LIST_MULTIPLIER; i++) {
887 uint32_t *rids;
888 const char *domain_name = NULL;
889 const char **names;
890 enum lsa_SidType *types;
891 struct lsa_dom_info *dom = &dom_infos[i];
893 if (!dom->valid) {
894 /* No domains left, we're done */
895 break;
898 if (dom->num_idxs) {
899 if (!(rids = talloc_array(tmp_ctx, uint32, dom->num_idxs))) {
900 result = NT_STATUS_NO_MEMORY;
901 goto fail;
903 } else {
904 rids = NULL;
907 for (j=0; j<dom->num_idxs; j++) {
908 rids[j] = name_infos[dom->idxs[j]].rid;
911 if (!lookup_rids(tmp_ctx, &dom->sid,
912 dom->num_idxs, rids, &domain_name,
913 &names, &types)) {
914 result = NT_STATUS_NO_MEMORY;
915 goto fail;
918 if (!(dom->name = talloc_strdup(dom_infos, domain_name))) {
919 result = NT_STATUS_NO_MEMORY;
920 goto fail;
923 for (j=0; j<dom->num_idxs; j++) {
924 int idx = dom->idxs[j];
925 name_infos[idx].type = types[j];
926 if (types[j] != SID_NAME_UNKNOWN) {
927 name_infos[idx].name =
928 talloc_strdup(name_infos, names[j]);
929 if (name_infos[idx].name == NULL) {
930 result = NT_STATUS_NO_MEMORY;
931 goto fail;
933 } else {
934 name_infos[idx].name = NULL;
939 *ret_domains = dom_infos;
940 *ret_names = name_infos;
941 TALLOC_FREE(tmp_ctx);
942 return NT_STATUS_OK;
944 fail:
945 TALLOC_FREE(dom_infos);
946 TALLOC_FREE(name_infos);
947 TALLOC_FREE(tmp_ctx);
948 return result;
951 /*****************************************************************
952 *THE CANONICAL* convert SID to name function.
953 *****************************************************************/
955 bool lookup_sid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
956 const char **ret_domain, const char **ret_name,
957 enum lsa_SidType *ret_type)
959 struct lsa_dom_info *domain;
960 struct lsa_name_info *name;
961 TALLOC_CTX *tmp_ctx;
962 bool ret = false;
964 DEBUG(10, ("lookup_sid called for SID '%s'\n", sid_string_dbg(sid)));
966 if (!(tmp_ctx = talloc_new(mem_ctx))) {
967 DEBUG(0, ("talloc_new failed\n"));
968 return false;
971 if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
972 &domain, &name))) {
973 goto done;
976 if (name->type == SID_NAME_UNKNOWN) {
977 goto done;
980 if ((ret_domain != NULL) &&
981 !(*ret_domain = talloc_strdup(mem_ctx, domain->name))) {
982 goto done;
985 if ((ret_name != NULL) &&
986 !(*ret_name = talloc_strdup(mem_ctx, name->name))) {
987 goto done;
990 if (ret_type != NULL) {
991 *ret_type = name->type;
994 ret = true;
996 done:
997 if (ret) {
998 DEBUG(10, ("Sid %s -> %s\\%s(%d)\n", sid_string_dbg(sid),
999 domain->name, name->name, name->type));
1000 } else {
1001 DEBUG(10, ("failed to lookup sid %s\n", sid_string_dbg(sid)));
1003 TALLOC_FREE(tmp_ctx);
1004 return ret;
1007 /*****************************************************************
1008 Id mapping cache. This is to avoid Winbind mappings already
1009 seen by smbd to be queried too frequently, keeping winbindd
1010 busy, and blocking smbd while winbindd is busy with other
1011 stuff. Written by Michael Steffens <michael.steffens@hp.com>,
1012 modified to use linked lists by jra.
1013 *****************************************************************/
1016 /*****************************************************************
1017 *THE LEGACY* convert uid_t to SID function.
1018 *****************************************************************/
1020 static void legacy_uid_to_sid(struct dom_sid *psid, uid_t uid)
1022 bool ret;
1024 ZERO_STRUCTP(psid);
1026 become_root();
1027 ret = pdb_uid_to_sid(uid, psid);
1028 unbecome_root();
1030 if (ret) {
1031 /* This is a mapped user */
1032 goto done;
1035 /* This is an unmapped user */
1037 uid_to_unix_users_sid(uid, psid);
1039 done:
1040 DEBUG(10,("LEGACY: uid %u -> sid %s\n", (unsigned int)uid,
1041 sid_string_dbg(psid)));
1043 return;
1046 /*****************************************************************
1047 *THE LEGACY* convert gid_t to SID function.
1048 *****************************************************************/
1050 static void legacy_gid_to_sid(struct dom_sid *psid, gid_t gid)
1052 bool ret;
1054 ZERO_STRUCTP(psid);
1056 become_root();
1057 ret = pdb_gid_to_sid(gid, psid);
1058 unbecome_root();
1060 if (ret) {
1061 /* This is a mapped group */
1062 goto done;
1065 /* This is an unmapped group */
1067 gid_to_unix_groups_sid(gid, psid);
1069 done:
1070 DEBUG(10,("LEGACY: gid %u -> sid %s\n", (unsigned int)gid,
1071 sid_string_dbg(psid)));
1073 return;
1076 /*****************************************************************
1077 *THE LEGACY* convert SID to uid function.
1078 *****************************************************************/
1080 static bool legacy_sid_to_uid(const struct dom_sid *psid, uid_t *puid)
1082 enum lsa_SidType type;
1084 if (sid_check_is_in_our_domain(psid)) {
1085 uid_t uid;
1086 gid_t gid;
1087 bool ret;
1089 become_root();
1090 ret = pdb_sid_to_id(psid, &uid, &gid, &type);
1091 unbecome_root();
1093 if (ret) {
1094 if (type != SID_NAME_USER) {
1095 DEBUG(5, ("sid %s is a %s, expected a user\n",
1096 sid_string_dbg(psid),
1097 sid_type_lookup(type)));
1098 return false;
1100 *puid = uid;
1101 goto done;
1104 /* This was ours, but it was not mapped. Fail */
1107 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1108 sid_string_dbg(psid)));
1109 return false;
1111 done:
1112 DEBUG(10,("LEGACY: sid %s -> uid %u\n", sid_string_dbg(psid),
1113 (unsigned int)*puid ));
1115 return true;
1118 /*****************************************************************
1119 *THE LEGACY* convert SID to gid function.
1120 Group mapping is used for gids that maps to Wellknown SIDs
1121 *****************************************************************/
1123 static bool legacy_sid_to_gid(const struct dom_sid *psid, gid_t *pgid)
1125 GROUP_MAP *map;
1126 enum lsa_SidType type;
1128 map = talloc_zero(NULL, GROUP_MAP);
1129 if (!map) {
1130 return false;
1133 if ((sid_check_is_in_builtin(psid) ||
1134 sid_check_is_in_wellknown_domain(psid))) {
1135 bool ret;
1137 become_root();
1138 ret = pdb_getgrsid(map, *psid);
1139 unbecome_root();
1141 if (ret) {
1142 *pgid = map->gid;
1143 goto done;
1145 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1146 sid_string_dbg(psid)));
1147 return false;
1150 if (sid_check_is_in_our_domain(psid)) {
1151 uid_t uid;
1152 gid_t gid;
1153 bool ret;
1155 become_root();
1156 ret = pdb_sid_to_id(psid, &uid, &gid, &type);
1157 unbecome_root();
1159 if (ret) {
1160 if ((type != SID_NAME_DOM_GRP) &&
1161 (type != SID_NAME_ALIAS)) {
1162 DEBUG(5, ("LEGACY: sid %s is a %s, expected "
1163 "a group\n", sid_string_dbg(psid),
1164 sid_type_lookup(type)));
1165 return false;
1167 *pgid = gid;
1168 goto done;
1171 /* This was ours, but it was not mapped. Fail */
1174 DEBUG(10,("LEGACY: mapping failed for sid %s\n",
1175 sid_string_dbg(psid)));
1176 return false;
1178 done:
1179 DEBUG(10,("LEGACY: sid %s -> gid %u\n", sid_string_dbg(psid),
1180 (unsigned int)*pgid ));
1182 TALLOC_FREE(map);
1183 return true;
1186 /*****************************************************************
1187 *THE CANONICAL* convert uid_t to SID function.
1188 *****************************************************************/
1190 void uid_to_sid(struct dom_sid *psid, uid_t uid)
1192 bool expired = true;
1193 bool ret;
1194 ZERO_STRUCTP(psid);
1196 /* Check the winbindd cache directly. */
1197 ret = idmap_cache_find_uid2sid(uid, psid, &expired);
1199 if (ret && !expired && is_null_sid(psid)) {
1201 * Negative cache entry, we already asked.
1202 * do legacy.
1204 legacy_uid_to_sid(psid, uid);
1205 return;
1208 if (!ret || expired) {
1209 /* Not in cache. Ask winbindd. */
1210 if (!winbind_uid_to_sid(psid, uid)) {
1212 * We shouldn't return the NULL SID
1213 * here if winbind was running and
1214 * couldn't map, as winbind will have
1215 * added a negative entry that will
1216 * cause us to go though the
1217 * legacy_uid_to_sid()
1218 * function anyway in the case above
1219 * the next time we ask.
1221 DEBUG(5, ("uid_to_sid: winbind failed to find a sid "
1222 "for uid %u\n", (unsigned int)uid));
1224 legacy_uid_to_sid(psid, uid);
1225 return;
1229 DEBUG(10,("uid %u -> sid %s\n", (unsigned int)uid,
1230 sid_string_dbg(psid)));
1232 return;
1235 /*****************************************************************
1236 *THE CANONICAL* convert gid_t to SID function.
1237 *****************************************************************/
1239 void gid_to_sid(struct dom_sid *psid, gid_t gid)
1241 bool expired = true;
1242 bool ret;
1243 ZERO_STRUCTP(psid);
1245 /* Check the winbindd cache directly. */
1246 ret = idmap_cache_find_gid2sid(gid, psid, &expired);
1248 if (ret && !expired && is_null_sid(psid)) {
1250 * Negative cache entry, we already asked.
1251 * do legacy.
1253 legacy_gid_to_sid(psid, gid);
1254 return;
1257 if (!ret || expired) {
1258 /* Not in cache. Ask winbindd. */
1259 if (!winbind_gid_to_sid(psid, gid)) {
1261 * We shouldn't return the NULL SID
1262 * here if winbind was running and
1263 * couldn't map, as winbind will have
1264 * added a negative entry that will
1265 * cause us to go though the
1266 * legacy_gid_to_sid()
1267 * function anyway in the case above
1268 * the next time we ask.
1270 DEBUG(5, ("gid_to_sid: winbind failed to find a sid "
1271 "for gid %u\n", (unsigned int)gid));
1273 legacy_gid_to_sid(psid, gid);
1274 return;
1278 DEBUG(10,("gid %u -> sid %s\n", (unsigned int)gid,
1279 sid_string_dbg(psid)));
1281 return;
1284 bool sids_to_unix_ids(const struct dom_sid *sids, uint32_t num_sids,
1285 struct wbcUnixId *ids)
1287 struct wbcDomainSid *wbc_sids = NULL;
1288 struct wbcUnixId *wbc_ids = NULL;
1289 uint32_t i, num_not_cached;
1290 wbcErr err;
1291 bool ret = false;
1293 wbc_sids = talloc_array(talloc_tos(), struct wbcDomainSid, num_sids);
1294 if (wbc_sids == NULL) {
1295 return false;
1298 num_not_cached = 0;
1300 for (i=0; i<num_sids; i++) {
1301 bool expired;
1302 uint32_t rid;
1304 if (sid_peek_check_rid(&global_sid_Unix_Users,
1305 &sids[i], &rid)) {
1306 ids[i].type = WBC_ID_TYPE_UID;
1307 ids[i].id.uid = rid;
1308 continue;
1310 if (sid_peek_check_rid(&global_sid_Unix_Groups,
1311 &sids[i], &rid)) {
1312 ids[i].type = WBC_ID_TYPE_GID;
1313 ids[i].id.gid = rid;
1314 continue;
1316 if (idmap_cache_find_sid2uid(&sids[i], &ids[i].id.uid,
1317 &expired)
1318 && !expired) {
1319 ids[i].type = WBC_ID_TYPE_UID;
1320 continue;
1322 if (idmap_cache_find_sid2gid(&sids[i], &ids[i].id.gid,
1323 &expired)
1324 && !expired) {
1325 ids[i].type = WBC_ID_TYPE_GID;
1326 continue;
1328 ids[i].type = WBC_ID_TYPE_NOT_SPECIFIED;
1329 memcpy(&wbc_sids[num_not_cached], &sids[i],
1330 ndr_size_dom_sid(&sids[i], 0));
1331 num_not_cached += 1;
1333 if (num_not_cached == 0) {
1334 goto done;
1336 wbc_ids = talloc_array(talloc_tos(), struct wbcUnixId, num_not_cached);
1337 if (wbc_ids == NULL) {
1338 goto fail;
1340 for (i=0; i<num_not_cached; i++) {
1341 wbc_ids[i].type = WBC_ID_TYPE_NOT_SPECIFIED;
1343 err = wbcSidsToUnixIds(wbc_sids, num_not_cached, wbc_ids);
1344 if (!WBC_ERROR_IS_OK(err)) {
1345 DEBUG(10, ("wbcSidsToUnixIds returned %s\n",
1346 wbcErrorString(err)));
1349 num_not_cached = 0;
1351 for (i=0; i<num_sids; i++) {
1352 if (ids[i].type == WBC_ID_TYPE_NOT_SPECIFIED) {
1353 ids[i] = wbc_ids[num_not_cached];
1354 num_not_cached += 1;
1358 for (i=0; i<num_sids; i++) {
1359 if (ids[i].type != WBC_ID_TYPE_NOT_SPECIFIED) {
1360 continue;
1362 if (legacy_sid_to_gid(&sids[i], &ids[i].id.gid)) {
1363 ids[i].type = WBC_ID_TYPE_GID;
1364 continue;
1366 if (legacy_sid_to_uid(&sids[i], &ids[i].id.uid)) {
1367 ids[i].type = WBC_ID_TYPE_UID;
1368 continue;
1371 done:
1372 ret = true;
1373 fail:
1374 TALLOC_FREE(wbc_ids);
1375 TALLOC_FREE(wbc_sids);
1376 return ret;
1379 /*****************************************************************
1380 *THE CANONICAL* convert SID to uid function.
1381 *****************************************************************/
1383 bool sid_to_uid(const struct dom_sid *psid, uid_t *puid)
1385 bool expired = true;
1386 bool ret;
1387 uint32 rid;
1389 /* Optimize for the Unix Users Domain
1390 * as the conversion is straightforward */
1391 if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
1392 uid_t uid = rid;
1393 *puid = uid;
1395 /* return here, don't cache */
1396 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1397 (unsigned int)*puid ));
1398 return true;
1401 /* Check the winbindd cache directly. */
1402 ret = idmap_cache_find_sid2uid(psid, puid, &expired);
1404 if (ret && !expired && (*puid == (uid_t)-1)) {
1406 * Negative cache entry, we already asked.
1407 * do legacy.
1409 return legacy_sid_to_uid(psid, puid);
1412 if (!ret || expired) {
1413 /* Not in cache. Ask winbindd. */
1414 if (!winbind_sid_to_uid(puid, psid)) {
1415 DEBUG(5, ("winbind failed to find a uid for sid %s\n",
1416 sid_string_dbg(psid)));
1417 /* winbind failed. do legacy */
1418 return legacy_sid_to_uid(psid, puid);
1422 /* TODO: Here would be the place to allocate both a gid and a uid for
1423 * the SID in question */
1425 DEBUG(10,("sid %s -> uid %u\n", sid_string_dbg(psid),
1426 (unsigned int)*puid ));
1428 return true;
1431 /*****************************************************************
1432 *THE CANONICAL* convert SID to gid function.
1433 Group mapping is used for gids that maps to Wellknown SIDs
1434 *****************************************************************/
1436 bool sid_to_gid(const struct dom_sid *psid, gid_t *pgid)
1438 bool expired = true;
1439 bool ret;
1440 uint32 rid;
1442 /* Optimize for the Unix Groups Domain
1443 * as the conversion is straightforward */
1444 if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
1445 gid_t gid = rid;
1446 *pgid = gid;
1448 /* return here, don't cache */
1449 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1450 (unsigned int)*pgid ));
1451 return true;
1454 /* Check the winbindd cache directly. */
1455 ret = idmap_cache_find_sid2gid(psid, pgid, &expired);
1457 if (ret && !expired && (*pgid == (gid_t)-1)) {
1459 * Negative cache entry, we already asked.
1460 * do legacy.
1462 return legacy_sid_to_gid(psid, pgid);
1465 if (!ret || expired) {
1466 /* Not in cache or negative. Ask winbindd. */
1467 /* Ask winbindd if it can map this sid to a gid.
1468 * (Idmap will check it is a valid SID and of the right type) */
1470 if ( !winbind_sid_to_gid(pgid, psid) ) {
1472 DEBUG(10,("winbind failed to find a gid for sid %s\n",
1473 sid_string_dbg(psid)));
1474 /* winbind failed. do legacy */
1475 return legacy_sid_to_gid(psid, pgid);
1479 DEBUG(10,("sid %s -> gid %u\n", sid_string_dbg(psid),
1480 (unsigned int)*pgid ));
1482 return true;
1486 * @brief This function gets the primary group SID mapping the primary
1487 * GID of the user as obtained by an actual getpwnam() call.
1488 * This is necessary to avoid issues with arbitrary group SIDs
1489 * stored in passdb. We try as hard as we can to get the SID
1490 * corresponding to the GID, including trying group mapping.
1491 * If nothing else works, we will force "Domain Users" as the
1492 * primary group.
1493 * This is needed because we must always be able to lookup the
1494 * primary group SID, so we cannot settle for an arbitrary SID.
1496 * This call can be expensive. Use with moderation.
1497 * If you have a "samu" struct around use pdb_get_group_sid()
1498 * instead as it does properly cache results.
1500 * @param mem_ctx[in] The memory context iused to allocate the result.
1501 * @param username[in] The user's name
1502 * @param _pwd[in|out] If available, pass in user's passwd struct.
1503 * It will contain a tallocated passwd if NULL was
1504 * passed in.
1505 * @param _group_sid[out] The user's Primary Group SID
1507 * @return NTSTATUS error code.
1509 NTSTATUS get_primary_group_sid(TALLOC_CTX *mem_ctx,
1510 const char *username,
1511 struct passwd **_pwd,
1512 struct dom_sid **_group_sid)
1514 TALLOC_CTX *tmp_ctx;
1515 bool need_lookup_sid = false;
1516 struct dom_sid *group_sid;
1517 struct passwd *pwd = *_pwd;
1519 tmp_ctx = talloc_new(mem_ctx);
1520 if (!tmp_ctx) {
1521 return NT_STATUS_NO_MEMORY;
1524 if (!pwd) {
1525 pwd = Get_Pwnam_alloc(mem_ctx, username);
1526 if (!pwd) {
1527 DEBUG(0, ("Failed to find a Unix account for %s",
1528 username));
1529 TALLOC_FREE(tmp_ctx);
1530 return NT_STATUS_NO_SUCH_USER;
1534 group_sid = talloc_zero(mem_ctx, struct dom_sid);
1535 if (!group_sid) {
1536 TALLOC_FREE(tmp_ctx);
1537 return NT_STATUS_NO_MEMORY;
1540 gid_to_sid(group_sid, pwd->pw_gid);
1541 if (!is_null_sid(group_sid)) {
1542 struct dom_sid domain_sid;
1543 uint32_t rid;
1545 /* We need a sid within our domain */
1546 sid_copy(&domain_sid, group_sid);
1547 sid_split_rid(&domain_sid, &rid);
1548 if (dom_sid_equal(&domain_sid, get_global_sam_sid())) {
1550 * As shortcut for the expensive lookup_sid call
1551 * compare the domain sid part
1553 switch (rid) {
1554 case DOMAIN_RID_ADMINS:
1555 case DOMAIN_RID_USERS:
1556 goto done;
1557 default:
1558 need_lookup_sid = true;
1559 break;
1561 } else {
1562 /* Try group mapping */
1563 ZERO_STRUCTP(group_sid);
1564 if (pdb_gid_to_sid(pwd->pw_gid, group_sid)) {
1565 need_lookup_sid = true;
1570 /* We must verify that this is a valid SID that resolves to a
1571 * group of the correct type */
1572 if (need_lookup_sid) {
1573 enum lsa_SidType type = SID_NAME_UNKNOWN;
1574 bool lookup_ret;
1576 DEBUG(10, ("do lookup_sid(%s) for group of user %s\n",
1577 sid_string_dbg(group_sid), username));
1579 /* Now check that it's actually a domain group and
1580 * not something else */
1581 lookup_ret = lookup_sid(tmp_ctx, group_sid,
1582 NULL, NULL, &type);
1584 if (lookup_ret && (type == SID_NAME_DOM_GRP)) {
1585 goto done;
1588 DEBUG(3, ("Primary group %s for user %s is"
1589 " a %s and not a domain group\n",
1590 sid_string_dbg(group_sid), username,
1591 sid_type_lookup(type)));
1594 /* Everything else, failed.
1595 * Just set it to the 'Domain Users' RID of 513 which will
1596 always resolve to a name */
1597 DEBUG(3, ("Forcing Primary Group to 'Domain Users' for %s\n",
1598 username));
1600 sid_compose(group_sid, get_global_sam_sid(), DOMAIN_RID_USERS);
1602 done:
1603 *_pwd = talloc_move(mem_ctx, &pwd);
1604 *_group_sid = talloc_move(mem_ctx, &group_sid);
1605 TALLOC_FREE(tmp_ctx);
1606 return NT_STATUS_OK;