python/tests: Fix nlink test in smb3unix on btrfs filesystem
[asn/samba-autobuild/.git] / auth / wbc_auth_util.c
1 /*
2    Unix SMB/CIFS implementation.
3    Authentication utility functions
4    Copyright (C) Volker Lendecke 2010
5
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.
10
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.
15
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/>.
18 */
19
20 #include "includes.h"
21 #include "libcli/security/security.h"
22 #include "librpc/gen_ndr/netlogon.h"
23 #include "nsswitch/libwbclient/wbclient.h"
24 #include "librpc/gen_ndr/auth.h"
25 #include "auth/auth_sam_reply.h"
26
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_AUTH
29
30 static NTSTATUS wbcsids_to_samr_RidWithAttributeArray(
31                                 TALLOC_CTX *mem_ctx,
32                                 struct samr_RidWithAttributeArray *groups,
33                                 const struct dom_sid *domain_sid,
34                                 const struct wbcSidWithAttr *sids,
35                                 size_t num_sids)
36 {
37         unsigned int i, j = 0;
38         bool ok;
39
40         groups->rids = talloc_array(mem_ctx,
41                                     struct samr_RidWithAttribute, num_sids);
42         if (!groups->rids) {
43                 return NT_STATUS_NO_MEMORY;
44         }
45
46         /* a wbcDomainSid is the same as a dom_sid */
47         for (i = 0; i < num_sids; i++) {
48                 ok = sid_peek_check_rid(domain_sid,
49                                         (const struct dom_sid *)&sids[i].sid,
50                                         &groups->rids[j].rid);
51                 if (!ok) continue;
52
53                 groups->rids[j].attributes = SE_GROUP_DEFAULT_FLAGS;
54                 j++;
55         }
56
57         groups->count = j;
58         return NT_STATUS_OK;
59 }
60
61 static NTSTATUS wbcsids_to_netr_SidAttrArray(
62                                 const struct dom_sid *domain_sid,
63                                 const struct wbcSidWithAttr *sids,
64                                 size_t num_sids,
65                                 TALLOC_CTX *mem_ctx,
66                                 struct netr_SidAttr **_info3_sids,
67                                 uint32_t *info3_num_sids)
68 {
69         unsigned int i, j = 0;
70         struct netr_SidAttr *info3_sids;
71
72         info3_sids = talloc_array(mem_ctx, struct netr_SidAttr, num_sids);
73         if (info3_sids == NULL) {
74                 return NT_STATUS_NO_MEMORY;
75         }
76
77         /* a wbcDomainSid is the same as a dom_sid */
78         for (i = 0; i < num_sids; i++) {
79                 const struct dom_sid *sid;
80
81                 sid = (const struct dom_sid *)&sids[i].sid;
82
83                 if (dom_sid_in_domain(domain_sid, sid)) {
84                         continue;
85                 }
86
87                 info3_sids[j].sid = dom_sid_dup(info3_sids, sid);
88                 if (info3_sids[j].sid == NULL) {
89                         talloc_free(info3_sids);
90                         return NT_STATUS_NO_MEMORY;
91                 }
92                 info3_sids[j].attributes = SE_GROUP_DEFAULT_FLAGS;
93                 j++;
94         }
95
96         *info3_num_sids = j;
97         *_info3_sids = info3_sids;
98         return NT_STATUS_OK;
99 }
100
101 #undef RET_NOMEM
102
103 #define RET_NOMEM(ptr) do { \
104         if (!ptr) { \
105                 TALLOC_FREE(info6); \
106                 return NULL; \
107         } } while(0)
108
109 struct netr_SamInfo6 *wbcAuthUserInfo_to_netr_SamInfo6(TALLOC_CTX *mem_ctx,
110                                         const struct wbcAuthUserInfo *info)
111 {
112         struct netr_SamInfo6 *info6;
113         struct dom_sid user_sid;
114         struct dom_sid group_sid;
115         struct dom_sid domain_sid;
116         NTSTATUS status;
117         bool ok;
118
119         memcpy(&user_sid, &info->sids[PRIMARY_USER_SID_INDEX].sid, sizeof(user_sid));
120         memcpy(&group_sid, &info->sids[PRIMARY_GROUP_SID_INDEX].sid, sizeof(group_sid));
121
122         info6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
123         if (!info6) return NULL;
124
125         unix_to_nt_time(&info6->base.logon_time, info->logon_time);
126         unix_to_nt_time(&info6->base.logoff_time, info->logoff_time);
127         unix_to_nt_time(&info6->base.kickoff_time, info->kickoff_time);
128         unix_to_nt_time(&info6->base.last_password_change, info->pass_last_set_time);
129         unix_to_nt_time(&info6->base.allow_password_change,
130                         info->pass_can_change_time);
131         unix_to_nt_time(&info6->base.force_password_change,
132                         info->pass_must_change_time);
133
134         if (info->account_name) {
135                 info6->base.account_name.string =
136                                 talloc_strdup(info6, info->account_name);
137                 RET_NOMEM(info6->base.account_name.string);
138         }
139         if (info->user_principal) {
140                 info6->principal_name.string    =
141                                 talloc_strdup(info6, info->user_principal);
142                 RET_NOMEM(info6->principal_name.string);
143         }
144         if (info->full_name) {
145                 info6->base.full_name.string =
146                                 talloc_strdup(info6, info->full_name);
147                 RET_NOMEM(info6->base.full_name.string);
148         }
149         if (info->domain_name) {
150                 info6->base.logon_domain.string =
151                                 talloc_strdup(info6, info->domain_name);
152                 RET_NOMEM(info6->base.logon_domain.string);
153         }
154         if (info->dns_domain_name) {
155                 info6->dns_domainname.string    =
156                                 talloc_strdup(info6, info->dns_domain_name);
157                 RET_NOMEM(info6->dns_domainname.string);
158         }
159         if (info->logon_script) {
160                 info6->base.logon_script.string =
161                                 talloc_strdup(info6, info->logon_script);
162                 RET_NOMEM(info6->base.logon_script.string);
163         }
164         if (info->profile_path) {
165                 info6->base.profile_path.string =
166                                 talloc_strdup(info6, info->profile_path);
167                 RET_NOMEM(info6->base.profile_path.string);
168         }
169         if (info->home_directory) {
170                 info6->base.home_directory.string =
171                                 talloc_strdup(info6, info->home_directory);
172                 RET_NOMEM(info6->base.home_directory.string);
173         }
174         if (info->home_drive) {
175                 info6->base.home_drive.string =
176                                 talloc_strdup(info6, info->home_drive);
177                 RET_NOMEM(info6->base.home_drive.string);
178         }
179
180         info6->base.logon_count = info->logon_count;
181         info6->base.bad_password_count = info->bad_password_count;
182
183         sid_copy(&domain_sid, &user_sid);
184         sid_split_rid(&domain_sid, &info6->base.rid);
185
186         ok = sid_peek_check_rid(&domain_sid, &group_sid,
187                                 &info6->base.primary_gid);
188         if (!ok) {
189                 DEBUG(1, ("The primary group sid domain does not"
190                           "match user sid domain for user: %s\n",
191                           info->account_name));
192                 TALLOC_FREE(info6);
193                 return NULL;
194         }
195
196         status = wbcsids_to_samr_RidWithAttributeArray(info6,
197                                                        &info6->base.groups,
198                                                        &domain_sid,
199                                                        &info->sids[PRIMARY_GROUP_SID_INDEX],
200                                                        info->num_sids - 1);
201         if (!NT_STATUS_IS_OK(status)) {
202                 TALLOC_FREE(info6);
203                 return NULL;
204         }
205
206         status = wbcsids_to_netr_SidAttrArray(&domain_sid,
207                                               &info->sids[PRIMARY_GROUP_SID_INDEX],
208                                               info->num_sids - 1,
209                                               info6,
210                                               &info6->sids,
211                                               &info6->sidcount);
212         if (!NT_STATUS_IS_OK(status)) {
213                 TALLOC_FREE(info6);
214                 return NULL;
215         }
216
217         info6->base.user_flags = info->user_flags;
218         memcpy(info6->base.key.key, info->user_session_key, 16);
219
220         if (info->logon_server) {
221                 info6->base.logon_server.string =
222                                 talloc_strdup(info6, info->logon_server);
223                 RET_NOMEM(info6->base.logon_server.string);
224         }
225         if (info->domain_name) {
226                 info6->base.logon_domain.string =
227                                 talloc_strdup(info6, info->domain_name);
228                 RET_NOMEM(info6->base.logon_domain.string);
229         }
230
231         info6->base.domain_sid = dom_sid_dup(info6, &domain_sid);
232         RET_NOMEM(info6->base.domain_sid);
233
234         memcpy(info6->base.LMSessKey.key, info->lm_session_key, 8);
235         info6->base.acct_flags = info->acct_flags;
236
237         return info6;
238 }