auth: Move wbcAuthUserInfo_to_netr_SamInfo3 to the top level
[obnox/samba/samba-obnox.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
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_AUTH
27
28 static NTSTATUS wbcsids_to_samr_RidWithAttributeArray(
29                                 TALLOC_CTX *mem_ctx,
30                                 struct samr_RidWithAttributeArray *groups,
31                                 const struct dom_sid *domain_sid,
32                                 const struct wbcSidWithAttr *sids,
33                                 size_t num_sids)
34 {
35         unsigned int i, j = 0;
36         bool ok;
37
38         groups->rids = talloc_array(mem_ctx,
39                                     struct samr_RidWithAttribute, num_sids);
40         if (!groups->rids) {
41                 return NT_STATUS_NO_MEMORY;
42         }
43
44         /* a wbcDomainSid is the same as a dom_sid */
45         for (i = 0; i < num_sids; i++) {
46                 ok = sid_peek_check_rid(domain_sid,
47                                         (const struct dom_sid *)&sids[i].sid,
48                                         &groups->rids[j].rid);
49                 if (!ok) continue;
50
51                 groups->rids[j].attributes = SE_GROUP_MANDATORY |
52                                              SE_GROUP_ENABLED_BY_DEFAULT |
53                                              SE_GROUP_ENABLED;
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_MANDATORY |
93                                            SE_GROUP_ENABLED_BY_DEFAULT |
94                                            SE_GROUP_ENABLED;
95                 j++;
96         }
97
98         *info3_num_sids = j;
99         *_info3_sids = info3_sids;
100         return NT_STATUS_OK;
101 }
102
103 #undef RET_NOMEM
104
105 #define RET_NOMEM(ptr) do { \
106         if (!ptr) { \
107                 TALLOC_FREE(info3); \
108                 return NULL; \
109         } } while(0)
110
111 struct netr_SamInfo3 *wbcAuthUserInfo_to_netr_SamInfo3(TALLOC_CTX *mem_ctx,
112                                         const struct wbcAuthUserInfo *info)
113 {
114         struct netr_SamInfo3 *info3;
115         struct dom_sid user_sid;
116         struct dom_sid group_sid;
117         struct dom_sid domain_sid;
118         NTSTATUS status;
119         bool ok;
120
121         memcpy(&user_sid, &info->sids[0].sid, sizeof(user_sid));
122         memcpy(&group_sid, &info->sids[1].sid, sizeof(group_sid));
123
124         info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
125         if (!info3) return NULL;
126
127         unix_to_nt_time(&info3->base.logon_time, info->logon_time);
128         unix_to_nt_time(&info3->base.logoff_time, info->logoff_time);
129         unix_to_nt_time(&info3->base.kickoff_time, info->kickoff_time);
130         unix_to_nt_time(&info3->base.last_password_change, info->pass_last_set_time);
131         unix_to_nt_time(&info3->base.allow_password_change,
132                         info->pass_can_change_time);
133         unix_to_nt_time(&info3->base.force_password_change,
134                         info->pass_must_change_time);
135
136         if (info->account_name) {
137                 info3->base.account_name.string =
138                                 talloc_strdup(info3, info->account_name);
139                 RET_NOMEM(info3->base.account_name.string);
140         }
141         if (info->full_name) {
142                 info3->base.full_name.string =
143                                 talloc_strdup(info3, info->full_name);
144                 RET_NOMEM(info3->base.full_name.string);
145         }
146         if (info->logon_script) {
147                 info3->base.logon_script.string =
148                                 talloc_strdup(info3, info->logon_script);
149                 RET_NOMEM(info3->base.logon_script.string);
150         }
151         if (info->profile_path) {
152                 info3->base.profile_path.string =
153                                 talloc_strdup(info3, info->profile_path);
154                 RET_NOMEM(info3->base.profile_path.string);
155         }
156         if (info->home_directory) {
157                 info3->base.home_directory.string =
158                                 talloc_strdup(info3, info->home_directory);
159                 RET_NOMEM(info3->base.home_directory.string);
160         }
161         if (info->home_drive) {
162                 info3->base.home_drive.string =
163                                 talloc_strdup(info3, info->home_drive);
164                 RET_NOMEM(info3->base.home_drive.string);
165         }
166
167         info3->base.logon_count = info->logon_count;
168         info3->base.bad_password_count = info->bad_password_count;
169
170         sid_copy(&domain_sid, &user_sid);
171         sid_split_rid(&domain_sid, &info3->base.rid);
172
173         ok = sid_peek_check_rid(&domain_sid, &group_sid,
174                                 &info3->base.primary_gid);
175         if (!ok) {
176                 DEBUG(1, ("The primary group sid domain does not"
177                           "match user sid domain for user: %s\n",
178                           info->account_name));
179                 TALLOC_FREE(info3);
180                 return NULL;
181         }
182
183         status = wbcsids_to_samr_RidWithAttributeArray(info3,
184                                                        &info3->base.groups,
185                                                        &domain_sid,
186                                                        &info->sids[1],
187                                                        info->num_sids - 1);
188         if (!NT_STATUS_IS_OK(status)) {
189                 TALLOC_FREE(info3);
190                 return NULL;
191         }
192
193         status = wbcsids_to_netr_SidAttrArray(&domain_sid,
194                                               &info->sids[1],
195                                               info->num_sids - 1,
196                                               info3,
197                                               &info3->sids,
198                                               &info3->sidcount);
199         if (!NT_STATUS_IS_OK(status)) {
200                 TALLOC_FREE(info3);
201                 return NULL;
202         }
203
204         info3->base.user_flags = info->user_flags;
205         memcpy(info3->base.key.key, info->user_session_key, 16);
206
207         if (info->logon_server) {
208                 info3->base.logon_server.string =
209                                 talloc_strdup(info3, info->logon_server);
210                 RET_NOMEM(info3->base.logon_server.string);
211         }
212         if (info->domain_name) {
213                 info3->base.logon_domain.string =
214                                 talloc_strdup(info3, info->domain_name);
215                 RET_NOMEM(info3->base.logon_domain.string);
216         }
217
218         info3->base.domain_sid = dom_sid_dup(info3, &domain_sid);
219         RET_NOMEM(info3->base.domain_sid);
220
221         memcpy(info3->base.LMSessKey.key, info->lm_session_key, 8);
222         info3->base.acct_flags = info->acct_flags;
223
224         return info3;
225 }