ldb: move struct ldb_debug_ops to ldb_private.h
[samba.git] / source3 / auth / auth_sam.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Password and authentication handling
4    Copyright (C) Andrew Tridgell              1992-2000
5    Copyright (C) Luke Kenneth Casson Leighton 1996-2000
6    Copyright (C) Andrew Bartlett              2001-2003
7    Copyright (C) Gerald Carter                2003
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "auth.h"
25 #include "passdb.h"
26
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_AUTH
29
30 static NTSTATUS auth_sam_ignoredomain_auth(const struct auth_context *auth_context,
31                                            void *my_private_data,
32                                            TALLOC_CTX *mem_ctx,
33                                            const struct auth_usersupplied_info *user_info,
34                                            struct auth_serversupplied_info **server_info)
35 {
36         if (!user_info || !auth_context) {
37                 return NT_STATUS_UNSUCCESSFUL;
38         }
39
40         if (user_info->mapped.account_name == NULL ||
41             user_info->mapped.account_name[0] == '\0')
42         {
43                 return NT_STATUS_NOT_IMPLEMENTED;
44         }
45
46         DBG_DEBUG("Check auth for: [%s]\\[%s]\n",
47                   user_info->mapped.domain_name,
48                   user_info->mapped.account_name);
49
50         return check_sam_security(&auth_context->challenge, mem_ctx,
51                                   user_info, server_info);
52 }
53
54 /* module initialisation */
55 static NTSTATUS auth_init_sam_ignoredomain(
56         struct auth_context *auth_context,
57         const char *param,
58         struct auth_methods **auth_method)
59 {
60         struct auth_methods *result;
61
62         result = talloc_zero(auth_context, struct auth_methods);
63         if (result == NULL) {
64                 return NT_STATUS_NO_MEMORY;
65         }
66         result->auth = auth_sam_ignoredomain_auth;
67         result->name = "sam_ignoredomain";
68
69         *auth_method = result;
70         return NT_STATUS_OK;
71 }
72
73
74 /****************************************************************************
75 Check SAM security (above) but with a few extra checks.
76 ****************************************************************************/
77
78 static NTSTATUS auth_samstrict_auth(const struct auth_context *auth_context,
79                                     void *my_private_data,
80                                     TALLOC_CTX *mem_ctx,
81                                     const struct auth_usersupplied_info *user_info,
82                                     struct auth_serversupplied_info **server_info)
83 {
84         const char *effective_domain = NULL;
85         bool is_local_name, is_my_domain;
86
87         if (!user_info || !auth_context) {
88                 return NT_STATUS_LOGON_FAILURE;
89         }
90         effective_domain = user_info->mapped.domain_name;
91
92         if (user_info->mapped.account_name == NULL ||
93             user_info->mapped.account_name[0] == '\0')
94         {
95                 return NT_STATUS_NOT_IMPLEMENTED;
96         }
97
98         if (lp_server_role() == ROLE_DOMAIN_MEMBER) {
99                 const char *p = NULL;
100
101                 p = strchr_m(user_info->mapped.account_name, '@');
102                 if (p != NULL) {
103                         /*
104                          * This needs to go to the DC,
105                          * even if @ is the last character
106                          */
107                         return NT_STATUS_NOT_IMPLEMENTED;
108                 }
109         }
110
111         if (effective_domain == NULL) {
112                 effective_domain = "";
113         }
114
115         DBG_DEBUG("Check auth for: [%s]\\[%s]\n",
116                   effective_domain,
117                   user_info->mapped.account_name);
118
119
120         if (strequal(effective_domain, "") || strequal(effective_domain, ".")) {
121                 /*
122                  * An empty domain name or '.' should be handled
123                  * as the local SAM name.
124                  */
125                 effective_domain = lp_netbios_name();
126         }
127
128         is_local_name = is_myname(effective_domain);
129         is_my_domain  = strequal(effective_domain, lp_workgroup());
130
131         /* check whether or not we service this domain/workgroup name */
132
133         switch ( lp_server_role() ) {
134                 case ROLE_STANDALONE:
135                 case ROLE_DOMAIN_MEMBER:
136                         if ( !is_local_name ) {
137                                 DEBUG(6,("check_samstrict_security: %s is not one of my local names (%s)\n",
138                                         effective_domain, (lp_server_role() == ROLE_DOMAIN_MEMBER
139                                         ? "ROLE_DOMAIN_MEMBER" : "ROLE_STANDALONE") ));
140                                 return NT_STATUS_NOT_IMPLEMENTED;
141                         }
142
143                         break;
144                 case ROLE_DOMAIN_PDC:
145                 case ROLE_DOMAIN_BDC:
146                 case ROLE_IPA_DC:
147                         if (!is_local_name && !is_my_domain) {
148                                /* If we are running on a DC that has PASSDB module with domain
149                                 * information, check if DNS forest name is matching the domain
150                                 * name. This is the case of IPA domain controller when
151                                 * trusted AD DCs attempt to authenticate IPA users using
152                                 * the forest root domain (which is the only domain in IPA).
153                                 */
154                                 struct pdb_domain_info *dom_info = NULL;
155
156                                 dom_info = pdb_get_domain_info(mem_ctx);
157                                 if ((dom_info != NULL) && (dom_info->dns_forest != NULL)) {
158                                         is_my_domain = strequal(user_info->mapped.domain_name,
159                                                                 dom_info->dns_forest);
160                                 }
161
162                                 TALLOC_FREE(dom_info);
163                                 if (!is_my_domain) {
164                                         DEBUG(6,("check_samstrict_security: %s is not one "
165                                                  "of my local names or domain name (DC)\n",
166                                                  effective_domain));
167                                         return NT_STATUS_NOT_IMPLEMENTED;
168                                 }
169                         }
170
171                         break;
172                 default: /* name is ok */
173                         break;
174         }
175
176         return check_sam_security(&auth_context->challenge, mem_ctx,
177                                   user_info, server_info);
178 }
179
180 /* module initialisation */
181 static NTSTATUS auth_init_sam(
182         struct auth_context *auth_context,
183         const char *param,
184         struct auth_methods **auth_method)
185 {
186         struct auth_methods *result;
187
188         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
189             && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
190                 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the auth_sam module. \n"));
191                 DEBUGADD(0, ("You should not set 'auth methods' when running the AD DC.\n"));
192                 exit(1);
193         }
194
195         result = talloc_zero(auth_context, struct auth_methods);
196         if (result == NULL) {
197                 return NT_STATUS_NO_MEMORY;
198         }
199         result->auth = auth_samstrict_auth;
200         result->name = "sam";
201         *auth_method = result;
202         return NT_STATUS_OK;
203 }
204
205 static NTSTATUS auth_sam_netlogon3_auth(const struct auth_context *auth_context,
206                                         void *my_private_data,
207                                         TALLOC_CTX *mem_ctx,
208                                         const struct auth_usersupplied_info *user_info,
209                                         struct auth_serversupplied_info **server_info)
210 {
211         const char *effective_domain = NULL;
212         bool is_my_domain;
213
214         if (!user_info || !auth_context) {
215                 return NT_STATUS_LOGON_FAILURE;
216         }
217         effective_domain = user_info->mapped.domain_name;
218
219         if (user_info->mapped.account_name == NULL ||
220             user_info->mapped.account_name[0] == '\0')
221         {
222                 return NT_STATUS_NOT_IMPLEMENTED;
223         }
224
225         if (effective_domain == NULL) {
226                 effective_domain = "";
227         }
228
229         DBG_DEBUG("Check auth for: [%s]\\[%s]\n",
230                   effective_domain,
231                   user_info->mapped.account_name);
232
233         /* check whether or not we service this domain/workgroup name */
234
235         switch (lp_server_role()) {
236         case ROLE_DOMAIN_PDC:
237         case ROLE_DOMAIN_BDC:
238         case ROLE_IPA_DC:
239                 break;
240         default:
241                 DBG_ERR("Invalid server role\n");
242                 return NT_STATUS_INVALID_SERVER_STATE;
243         }
244
245         if (strequal(effective_domain, "") || strequal(effective_domain, ".")) {
246                 /*
247                  * An empty domain name or '.' should be handled
248                  * as the local SAM name.
249                  */
250                 effective_domain = lp_workgroup();
251         }
252
253         is_my_domain = strequal(user_info->mapped.domain_name, lp_workgroup());
254         if (!is_my_domain) {
255                /* If we are running on a DC that has PASSDB module with domain
256                 * information, check if DNS forest name is matching the domain
257                 * name. This is the case of IPA domain controller when
258                 * trusted AD DCs attempt to authenticate IPA users using
259                 * the forest root domain (which is the only domain in IPA).
260                 */
261                 struct pdb_domain_info *dom_info = NULL;
262                 dom_info = pdb_get_domain_info(mem_ctx);
263
264                 if ((dom_info != NULL) && (dom_info->dns_forest != NULL)) {
265                         is_my_domain = strequal(user_info->mapped.domain_name,
266                                                 dom_info->dns_forest);
267                 }
268
269                 TALLOC_FREE(dom_info);
270         }
271
272         if (!is_my_domain) {
273                 DBG_INFO("%s is not our domain name (DC for %s)\n",
274                          effective_domain, lp_workgroup());
275                 return NT_STATUS_NOT_IMPLEMENTED;
276         }
277
278         return check_sam_security(&auth_context->challenge, mem_ctx,
279                                   user_info, server_info);
280 }
281
282 /* module initialisation */
283 static NTSTATUS auth_init_sam_netlogon3(
284         struct auth_context *auth_context,
285         const char *param,
286         struct auth_methods **auth_method)
287 {
288         struct auth_methods *result;
289
290         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
291             && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
292                 DEBUG(0, ("server role = 'active directory domain controller' "
293                           "not compatible with running the auth_sam module.\n"));
294                 DEBUGADD(0, ("You should not set 'auth methods' when "
295                              "running the AD DC.\n"));
296                 exit(1);
297         }
298
299         result = talloc_zero(auth_context, struct auth_methods);
300         if (result == NULL) {
301                 return NT_STATUS_NO_MEMORY;
302         }
303         result->auth = auth_sam_netlogon3_auth;
304         result->name = "sam_netlogon3";
305         *auth_method = result;
306         return NT_STATUS_OK;
307 }
308
309 NTSTATUS auth_sam_init(TALLOC_CTX *mem_ctx)
310 {
311         smb_register_auth(AUTH_INTERFACE_VERSION, "sam", auth_init_sam);
312         smb_register_auth(AUTH_INTERFACE_VERSION, "sam_ignoredomain", auth_init_sam_ignoredomain);
313         smb_register_auth(AUTH_INTERFACE_VERSION, "sam_netlogon3", auth_init_sam_netlogon3);
314         return NT_STATUS_OK;
315 }