auth/ntlmssp: introduce ntlmssp_server_auth_send/recv
[vlendec/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_MANDATORY |
54                                              SE_GROUP_ENABLED_BY_DEFAULT |
55                                              SE_GROUP_ENABLED;
56                 j++;
57         }
58
59         groups->count = j;
60         return NT_STATUS_OK;
61 }
62
63 static NTSTATUS wbcsids_to_netr_SidAttrArray(
64                                 const struct dom_sid *domain_sid,
65                                 const struct wbcSidWithAttr *sids,
66                                 size_t num_sids,
67                                 TALLOC_CTX *mem_ctx,
68                                 struct netr_SidAttr **_info3_sids,
69                                 uint32_t *info3_num_sids)
70 {
71         unsigned int i, j = 0;
72         struct netr_SidAttr *info3_sids;
73
74         info3_sids = talloc_array(mem_ctx, struct netr_SidAttr, num_sids);
75         if (info3_sids == NULL) {
76                 return NT_STATUS_NO_MEMORY;
77         }
78
79         /* a wbcDomainSid is the same as a dom_sid */
80         for (i = 0; i < num_sids; i++) {
81                 const struct dom_sid *sid;
82
83                 sid = (const struct dom_sid *)&sids[i].sid;
84
85                 if (dom_sid_in_domain(domain_sid, sid)) {
86                         continue;
87                 }
88
89                 info3_sids[j].sid = dom_sid_dup(info3_sids, sid);
90                 if (info3_sids[j].sid == NULL) {
91                         talloc_free(info3_sids);
92                         return NT_STATUS_NO_MEMORY;
93                 }
94                 info3_sids[j].attributes = SE_GROUP_MANDATORY |
95                                            SE_GROUP_ENABLED_BY_DEFAULT |
96                                            SE_GROUP_ENABLED;
97                 j++;
98         }
99
100         *info3_num_sids = j;
101         *_info3_sids = info3_sids;
102         return NT_STATUS_OK;
103 }
104
105 #undef RET_NOMEM
106
107 #define RET_NOMEM(ptr) do { \
108         if (!ptr) { \
109                 TALLOC_FREE(info6); \
110                 return NULL; \
111         } } while(0)
112
113 struct netr_SamInfo6 *wbcAuthUserInfo_to_netr_SamInfo6(TALLOC_CTX *mem_ctx,
114                                         const struct wbcAuthUserInfo *info)
115 {
116         struct netr_SamInfo6 *info6;
117         struct dom_sid user_sid;
118         struct dom_sid group_sid;
119         struct dom_sid domain_sid;
120         NTSTATUS status;
121         bool ok;
122
123         memcpy(&user_sid, &info->sids[0].sid, sizeof(user_sid));
124         memcpy(&group_sid, &info->sids[1].sid, sizeof(group_sid));
125
126         info6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
127         if (!info6) return NULL;
128
129         unix_to_nt_time(&info6->base.logon_time, info->logon_time);
130         unix_to_nt_time(&info6->base.logoff_time, info->logoff_time);
131         unix_to_nt_time(&info6->base.kickoff_time, info->kickoff_time);
132         unix_to_nt_time(&info6->base.last_password_change, info->pass_last_set_time);
133         unix_to_nt_time(&info6->base.allow_password_change,
134                         info->pass_can_change_time);
135         unix_to_nt_time(&info6->base.force_password_change,
136                         info->pass_must_change_time);
137
138         if (info->account_name) {
139                 info6->base.account_name.string =
140                                 talloc_strdup(info6, info->account_name);
141                 RET_NOMEM(info6->base.account_name.string);
142         }
143         if (info->user_principal) {
144                 info6->principal_name.string    =
145                                 talloc_strdup(info6, info->user_principal);
146                 RET_NOMEM(info6->principal_name.string);
147         }
148         if (info->full_name) {
149                 info6->base.full_name.string =
150                                 talloc_strdup(info6, info->full_name);
151                 RET_NOMEM(info6->base.full_name.string);
152         }
153         if (info->domain_name) {
154                 info6->base.logon_domain.string =
155                                 talloc_strdup(info6, info->domain_name);
156                 RET_NOMEM(info6->base.logon_domain.string);
157         }
158         if (info->dns_domain_name) {
159                 info6->dns_domainname.string    =
160                                 talloc_strdup(info6, info->dns_domain_name);
161                 RET_NOMEM(info6->dns_domainname.string);
162         }
163         if (info->logon_script) {
164                 info6->base.logon_script.string =
165                                 talloc_strdup(info6, info->logon_script);
166                 RET_NOMEM(info6->base.logon_script.string);
167         }
168         if (info->profile_path) {
169                 info6->base.profile_path.string =
170                                 talloc_strdup(info6, info->profile_path);
171                 RET_NOMEM(info6->base.profile_path.string);
172         }
173         if (info->home_directory) {
174                 info6->base.home_directory.string =
175                                 talloc_strdup(info6, info->home_directory);
176                 RET_NOMEM(info6->base.home_directory.string);
177         }
178         if (info->home_drive) {
179                 info6->base.home_drive.string =
180                                 talloc_strdup(info6, info->home_drive);
181                 RET_NOMEM(info6->base.home_drive.string);
182         }
183
184         info6->base.logon_count = info->logon_count;
185         info6->base.bad_password_count = info->bad_password_count;
186
187         sid_copy(&domain_sid, &user_sid);
188         sid_split_rid(&domain_sid, &info6->base.rid);
189
190         ok = sid_peek_check_rid(&domain_sid, &group_sid,
191                                 &info6->base.primary_gid);
192         if (!ok) {
193                 DEBUG(1, ("The primary group sid domain does not"
194                           "match user sid domain for user: %s\n",
195                           info->account_name));
196                 TALLOC_FREE(info6);
197                 return NULL;
198         }
199
200         status = wbcsids_to_samr_RidWithAttributeArray(info6,
201                                                        &info6->base.groups,
202                                                        &domain_sid,
203                                                        &info->sids[1],
204                                                        info->num_sids - 1);
205         if (!NT_STATUS_IS_OK(status)) {
206                 TALLOC_FREE(info6);
207                 return NULL;
208         }
209
210         status = wbcsids_to_netr_SidAttrArray(&domain_sid,
211                                               &info->sids[1],
212                                               info->num_sids - 1,
213                                               info6,
214                                               &info6->sids,
215                                               &info6->sidcount);
216         if (!NT_STATUS_IS_OK(status)) {
217                 TALLOC_FREE(info6);
218                 return NULL;
219         }
220
221         info6->base.user_flags = info->user_flags;
222         memcpy(info6->base.key.key, info->user_session_key, 16);
223
224         if (info->logon_server) {
225                 info6->base.logon_server.string =
226                                 talloc_strdup(info6, info->logon_server);
227                 RET_NOMEM(info6->base.logon_server.string);
228         }
229         if (info->domain_name) {
230                 info6->base.logon_domain.string =
231                                 talloc_strdup(info6, info->domain_name);
232                 RET_NOMEM(info6->base.logon_domain.string);
233         }
234
235         info6->base.domain_sid = dom_sid_dup(info6, &domain_sid);
236         RET_NOMEM(info6->base.domain_sid);
237
238         memcpy(info6->base.LMSessKey.key, info->lm_session_key, 8);
239         info6->base.acct_flags = info->acct_flags;
240
241         return info6;
242 }