r6793: Move auth_sam to use the dnsDomain rather than the
[samba.git] / source / auth / auth_sam.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Password and authentication handling
4    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2001-2004
5    Copyright (C) Gerald Carter                             2003
6    Copyright (C) Stefan Metzmacher                         2005
7    
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 2 of the License, or
11    (at your option) any later version.
12    
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.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "librpc/gen_ndr/ndr_samr.h"
25 #include "system/time.h"
26 #include "auth/auth.h"
27 #include "lib/ldb/include/ldb.h"
28 #include "pstring.h"
29
30 /****************************************************************************
31  Do a specific test for an smb password being correct, given a smb_password and
32  the lanman and NT responses.
33 ****************************************************************************/
34 static NTSTATUS authsam_password_ok(const struct auth_context *auth_context,
35                                     TALLOC_CTX *mem_ctx,
36                                     uint16_t acct_flags,
37                                     const struct samr_Password *lm_pwd, 
38                                     const struct samr_Password *nt_pwd,
39                                     const struct auth_usersupplied_info *user_info, 
40                                     DATA_BLOB *user_sess_key, 
41                                     DATA_BLOB *lm_sess_key)
42 {
43         NTSTATUS status;
44
45         if (acct_flags & ACB_PWNOTREQ) {
46                 if (lp_null_passwords()) {
47                         DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", 
48                                  user_info->account_name));
49                         return NT_STATUS_OK;
50                 } else {
51                         DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", 
52                                  user_info->account_name));
53                         return NT_STATUS_LOGON_FAILURE;
54                 }               
55         }
56
57         status = ntlm_password_check(mem_ctx, &auth_context->challenge.data, 
58                                      &user_info->lm_resp, &user_info->nt_resp, 
59                                      &user_info->lm_interactive_password, 
60                                      &user_info->nt_interactive_password,
61                                      user_info->account_name,
62                                      user_info->client.account_name, 
63                                      user_info->client.domain_name, 
64                                      lm_pwd->hash, nt_pwd->hash,
65                                      user_sess_key, lm_sess_key);
66         NT_STATUS_NOT_OK_RETURN(status);
67
68         if (user_sess_key && user_sess_key->data) {
69                 talloc_steal(auth_context, user_sess_key->data);
70         }
71         if (lm_sess_key && lm_sess_key->data) {
72                 talloc_steal(auth_context, lm_sess_key->data);
73         }
74
75         return NT_STATUS_OK;
76 }
77
78
79 /****************************************************************************
80  Do a specific test for a SAM_ACCOUNT being vaild for this connection 
81  (ie not disabled, expired and the like).
82 ****************************************************************************/
83 static NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx,
84                                    uint16_t acct_flags,
85                                    NTTIME acct_expiry,
86                                    NTTIME must_change_time,
87                                    NTTIME last_set_time,
88                                    const char *workstation_list,
89                                    const struct auth_usersupplied_info *user_info)
90 {
91         DEBUG(4,("authsam_account_ok: Checking SMB password for user %s\n", user_info->account_name));
92
93         /* Quit if the account was disabled. */
94         if (acct_flags & ACB_DISABLED) {
95                 DEBUG(1,("authsam_account_ok: Account for user '%s' was disabled.\n", user_info->account_name));
96                 return NT_STATUS_ACCOUNT_DISABLED;
97         }
98
99         /* Quit if the account was locked out. */
100         if (acct_flags & ACB_AUTOLOCK) {
101                 DEBUG(1,("authsam_account_ok: Account for user %s was locked out.\n", user_info->account_name));
102                 return NT_STATUS_ACCOUNT_LOCKED_OUT;
103         }
104
105         /* Test account expire time */
106         if ((acct_expiry) != -1 && time(NULL) > nt_time_to_unix(acct_expiry)) {
107                 DEBUG(1,("authsam_account_ok: Account for user '%s' has expired.\n", user_info->account_name));
108                 DEBUG(3,("authsam_account_ok: Account expired at '%s'.\n", 
109                          nt_time_string(mem_ctx, acct_expiry)));
110                 return NT_STATUS_ACCOUNT_EXPIRED;
111         }
112
113         if (!(acct_flags & ACB_PWNOEXP)) {
114                 /* check for immediate expiry "must change at next logon" */
115                 if (must_change_time == 0 && last_set_time != 0) {
116                         DEBUG(1,("sam_account_ok: Account for user '%s' password must change!.\n", 
117                                  user_info->account_name));
118                         return NT_STATUS_PASSWORD_MUST_CHANGE;
119                 }
120
121                 /* check for expired password */
122                 if ((must_change_time) != 0 && nt_time_to_unix(must_change_time) < time(NULL)) {
123                         DEBUG(1,("sam_account_ok: Account for user '%s' password expired!.\n", 
124                                  user_info->account_name));
125                         DEBUG(1,("sam_account_ok: Password expired at '%s' unix time.\n", 
126                                  nt_time_string(mem_ctx, must_change_time)));
127                         return NT_STATUS_PASSWORD_EXPIRED;
128                 }
129         }
130
131         /* Test workstation. Workstation list is comma separated. */
132         if (workstation_list && *workstation_list) {
133                 BOOL invalid_ws = True;
134                 const char *s = workstation_list;
135                         
136                 fstring tok;
137                         
138                 while (next_token(&s, tok, ",", sizeof(tok))) {
139                         DEBUG(10,("sam_account_ok: checking for workstation match '%s' and '%s'\n",
140                                   tok, user_info->workstation_name));
141
142                         if (strequal(tok, user_info->workstation_name)) {
143                                 invalid_ws = False;
144
145                                 break;
146                         }
147                 }
148
149                 if (invalid_ws) {
150                         return NT_STATUS_INVALID_WORKSTATION;
151                 }
152         }
153
154         if (acct_flags & ACB_DOMTRUST) {
155                 DEBUG(2,("sam_account_ok: Domain trust account %s denied by server\n", user_info->account_name));
156                 return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT;
157         }
158
159         if (acct_flags & ACB_SVRTRUST) {
160                 DEBUG(2,("sam_account_ok: Server trust account %s denied by server\n", user_info->account_name));
161                 return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT;
162         }
163
164         if (acct_flags & ACB_WSTRUST) {
165                 DEBUG(4,("sam_account_ok: Wksta trust account %s denied by server\n", user_info->account_name));
166                 return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
167         }
168
169         return NT_STATUS_OK;
170 }
171
172 /****************************************************************************
173  Look for the specified user in the sam, return ldb result structures
174 ****************************************************************************/
175
176 static NTSTATUS authsam_search_account(TALLOC_CTX *mem_ctx, void *sam_ctx,
177                                        const char *account_name,
178                                        const char *domain_name,
179                                        struct ldb_message ***ret_msgs,
180                                        struct ldb_message ***ret_msgs_domain)
181 {
182         struct ldb_message **msgs;
183         struct ldb_message **msgs_domain;
184
185         int ret;
186         int ret_domain;
187
188         const char *domain_dn = NULL;
189
190         const char *attrs[] = {"unicodePwd", "lmPwdHash", "ntPwdHash",
191                                "userAccountControl",
192                                "pwdLastSet",
193                                "accountExpires",
194                                "objectSid",
195                                "userWorkstations",
196                                
197                                /* required for server_info, not access control: */
198                                "sAMAccountName",
199                                "displayName",
200                                "scriptPath",
201                                "profilePath",
202                                "homeDirectory",
203                                "homeDrive",
204                                "lastLogon",
205                                "lastLogoff",
206                                "accountExpires",
207                                "badPwdCount",
208                                "logonCount",
209                                "primaryGroupID",
210                                NULL,
211         };
212
213         const char *domain_attrs[] =  {"flatname", "objectSid"};
214
215         if (domain_name) {
216                 /* find the domain's DN */
217                 ret_domain = gendb_search(sam_ctx, mem_ctx, NULL, &msgs_domain, domain_attrs,
218                                           "(|(&(dnsDomain=%s)(objectClass=domainDNS))(&(flatname=%s)(objectclass=domain)))", 
219                                           domain_name, domain_name);
220                 if (ret_domain == -1) {
221                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
222                 }
223
224                 if (ret_domain == 0) {
225                         DEBUG(3,("sam_search_user: Couldn't find domain [%s] in samdb.\n", 
226                                  domain_name));
227                         return NT_STATUS_NO_SUCH_USER;
228                 }
229
230                 if (ret_domain > 1) {
231                         DEBUG(0,("Found %d records matching domain [%s]\n", 
232                                  ret_domain, domain_name));
233                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
234                 }
235
236                 domain_dn = msgs_domain[0]->dn;
237         }
238
239         /* pull the user attributes */
240         ret = gendb_search(sam_ctx, mem_ctx, domain_dn, &msgs, attrs,
241                            "(&(sAMAccountName=%s)(objectclass=user))", 
242                            account_name);
243         if (ret == -1) {
244                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
245         }
246
247         if (ret == 0) {
248                 DEBUG(3,("sam_search_user: Couldn't find user [%s] in samdb.\n", 
249                          account_name));
250                 return NT_STATUS_NO_SUCH_USER;
251         }
252
253         if (ret > 1) {
254                 DEBUG(0,("Found %d records matching user [%s]\n", ret, account_name));
255                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
256         }
257
258         if (!domain_name) {
259                 const char *domain_sid;
260
261                 domain_sid = samdb_result_sid_prefix(mem_ctx, msgs[0], "objectSid");
262                 if (!domain_sid) {
263                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
264                 }
265
266                 /* find the domain's DN */
267                 ret_domain = gendb_search(sam_ctx, mem_ctx, NULL, &msgs_domain, domain_attrs,
268                                           "(&(objectSid=%s)(objectclass=domain))", 
269                                           domain_sid);
270                 if (ret_domain == -1) {
271                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
272                 }
273                 
274                 if (ret_domain == 0) {
275                         DEBUG(3,("check_sam_security: Couldn't find domain [%s] in passdb file.\n",
276                                  domain_sid));
277                         return NT_STATUS_NO_SUCH_USER;
278                 }
279                 
280                 if (ret_domain > 1) {
281                         DEBUG(0,("Found %d records matching domain [%s]\n", 
282                                  ret_domain, domain_sid));
283                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
284                 }
285         }
286
287         *ret_msgs = msgs;
288         *ret_msgs_domain = msgs_domain;
289         
290         return NT_STATUS_OK;
291 }
292
293 static NTSTATUS authsam_authenticate(const struct auth_context *auth_context, 
294                                      TALLOC_CTX *mem_ctx, void *sam_ctx, 
295                                      struct ldb_message **msgs,
296                                      struct ldb_message **msgs_domain,
297                                      const struct auth_usersupplied_info *user_info, 
298                                      DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key) 
299 {
300         uint16_t acct_flags;
301         const char *workstation_list;
302         NTTIME acct_expiry;
303         NTTIME must_change_time;
304         NTTIME last_set_time;
305         struct samr_Password *lm_pwd, *nt_pwd;
306         NTSTATUS nt_status;
307         const char *domain_dn = msgs_domain[0]->dn;
308
309         acct_flags = samdb_result_acct_flags(msgs[0], "sAMAcctFlags");
310         
311         /* Quit if the account was locked out. */
312         if (acct_flags & ACB_AUTOLOCK) {
313                 DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", 
314                          user_info->account_name));
315                 return NT_STATUS_ACCOUNT_LOCKED_OUT;
316         }
317
318         nt_status = samdb_result_passwords(mem_ctx, msgs[0], &lm_pwd, &nt_pwd);
319         NT_STATUS_NOT_OK_RETURN(nt_status);
320
321         nt_status = authsam_password_ok(auth_context, mem_ctx, 
322                                         acct_flags, lm_pwd, nt_pwd,
323                                         user_info, user_sess_key, lm_sess_key);
324         NT_STATUS_NOT_OK_RETURN(nt_status);
325
326         acct_expiry = samdb_result_nttime(msgs[0], "accountExpires", 0);
327         must_change_time = samdb_result_force_password_change(sam_ctx, mem_ctx, 
328                                                               domain_dn, msgs[0], 
329                                                               "pwdLastSet");
330         last_set_time = samdb_result_nttime(msgs[0], "pwdLastSet", 0);
331
332         workstation_list = samdb_result_string(msgs[0], "userWorkstations", NULL);
333
334         nt_status = authsam_account_ok(mem_ctx, acct_flags, 
335                                        acct_expiry, 
336                                        must_change_time, 
337                                        last_set_time, 
338                                        workstation_list,
339                                        user_info);
340
341         return nt_status;
342 }
343
344 static NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, void *sam_ctx,
345                                          struct ldb_message **msgs,
346                                          struct ldb_message **msgs_domain,
347                                          DATA_BLOB user_sess_key, DATA_BLOB lm_sess_key,
348                                          struct auth_serversupplied_info **_server_info)
349 {
350         struct auth_serversupplied_info *server_info;
351         struct ldb_message **group_msgs;
352         int group_ret;
353         const char *group_attrs[3] = { "sAMAccountType", "objectSid", NULL }; 
354         /* find list of sids */
355         struct dom_sid **groupSIDs = NULL;
356         struct dom_sid *account_sid;
357         struct dom_sid *primary_group_sid;
358         const char *str;
359         int i;
360         uint_t rid;
361         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
362
363         group_ret = gendb_search(sam_ctx,
364                                  tmp_ctx, NULL, &group_msgs, group_attrs,
365                                  "(&(member=%s)(sAMAccountType=*))", 
366                                  msgs[0]->dn);
367         if (group_ret == -1) {
368                 talloc_free(tmp_ctx);
369                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
370         }
371
372         server_info = talloc(mem_ctx, struct auth_serversupplied_info);
373         NT_STATUS_HAVE_NO_MEMORY(server_info);
374         
375         if (group_ret > 0) {
376                 groupSIDs = talloc_array(server_info, struct dom_sid *, group_ret);
377                 NT_STATUS_HAVE_NO_MEMORY(groupSIDs);
378         }
379
380         /* Need to unroll some nested groups, but not aliases */
381         for (i = 0; i < group_ret; i++) {
382                 str = ldb_msg_find_string(group_msgs[i], "objectSid", NULL);
383                 groupSIDs[i] = dom_sid_parse_talloc(groupSIDs, str);
384                 NT_STATUS_HAVE_NO_MEMORY(groupSIDs[i]);
385         }
386
387         talloc_free(tmp_ctx);
388
389         str = ldb_msg_find_string(msgs[0], "objectSid", NULL);
390         account_sid = dom_sid_parse_talloc(server_info, str);
391         NT_STATUS_HAVE_NO_MEMORY(account_sid);
392
393         primary_group_sid = dom_sid_dup(server_info, account_sid);
394         NT_STATUS_HAVE_NO_MEMORY(primary_group_sid);
395
396         rid = samdb_result_uint(msgs[0], "primaryGroupID", ~0);
397         if (rid == ~0) {
398                 if (group_ret > 0) {
399                         primary_group_sid = groupSIDs[0];
400                 } else {
401                         primary_group_sid = NULL;
402                 }
403         } else {
404                 primary_group_sid->sub_auths[primary_group_sid->num_auths-1] = rid;
405         }
406
407         server_info->account_sid = account_sid;
408         server_info->primary_group_sid = primary_group_sid;
409         
410         server_info->n_domain_groups = group_ret;
411         server_info->domain_groups = groupSIDs;
412
413         server_info->account_name = talloc_reference(server_info, samdb_result_string(msgs[0], "sAMAccountName", NULL));
414
415         server_info->domain_name = talloc_reference(server_info, samdb_result_string(msgs_domain[0], "flatname", NULL));
416
417         str = samdb_result_string(msgs[0], "displayName", "");
418         server_info->full_name = talloc_strdup(server_info, str);
419         NT_STATUS_HAVE_NO_MEMORY(server_info->full_name);
420
421         str = samdb_result_string(msgs[0], "scriptPath", "");
422         server_info->logon_script = talloc_strdup(server_info, str);
423         NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script);
424
425         str = samdb_result_string(msgs[0], "profilePath", "");
426         server_info->profile_path = talloc_strdup(server_info, str);
427         NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path);
428
429         str = samdb_result_string(msgs[0], "homeDirectory", "");
430         server_info->home_directory = talloc_strdup(server_info, str);
431         NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory);
432
433         str = samdb_result_string(msgs[0], "homeDrive", "");
434         server_info->home_drive = talloc_strdup(server_info, str);
435         NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive);
436
437         server_info->last_logon = samdb_result_nttime(msgs[0], "lastLogon", 0);
438         server_info->last_logoff = samdb_result_nttime(msgs[0], "lastLogoff", 0);
439         server_info->acct_expiry = samdb_result_nttime(msgs[0], "accountExpires", 0);
440         server_info->last_password_change = samdb_result_nttime(msgs[0], "pwdLastSet", 0);
441
442         server_info->allow_password_change = samdb_result_allow_password_change(sam_ctx, mem_ctx, 
443                                                         msgs_domain[0]->dn, msgs[0], "pwdLastSet");
444         server_info->force_password_change = samdb_result_force_password_change(sam_ctx, mem_ctx, 
445                                                         msgs_domain[0]->dn, msgs[0], "pwdLastSet");
446
447         server_info->logon_count = samdb_result_uint(msgs[0], "logonCount", 0);
448         server_info->bad_password_count = samdb_result_uint(msgs[0], "badPwdCount", 0);
449
450         server_info->acct_flags = samdb_result_acct_flags(msgs[0], "userAccountControl");
451
452         server_info->user_session_key = user_sess_key;
453         server_info->lm_session_key = lm_sess_key;
454
455         server_info->authenticated = True;
456
457         *_server_info = server_info;
458
459         return NT_STATUS_OK;
460 }
461
462 NTSTATUS sam_get_server_info(TALLOC_CTX *mem_ctx, const char *account_name, const char *domain_name,
463                              DATA_BLOB user_sess_key, DATA_BLOB lm_sess_key,
464                              struct auth_serversupplied_info **server_info)
465 {
466         NTSTATUS nt_status;
467
468         struct ldb_message **msgs;
469         struct ldb_message **domain_msgs;
470         void *sam_ctx;
471
472         sam_ctx = samdb_connect(mem_ctx);
473         if (sam_ctx == NULL) {
474                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
475         }
476
477         nt_status = authsam_search_account(mem_ctx, sam_ctx, account_name, domain_name, &msgs, &domain_msgs);
478         NT_STATUS_NOT_OK_RETURN(nt_status);
479
480         nt_status = authsam_make_server_info(mem_ctx, sam_ctx, msgs, domain_msgs,
481                                              user_sess_key, lm_sess_key,
482                                              server_info);
483         NT_STATUS_NOT_OK_RETURN(nt_status);
484
485         talloc_free(msgs);
486         talloc_free(domain_msgs);
487
488         return NT_STATUS_OK;
489 }
490
491 static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx,
492                                                  TALLOC_CTX *mem_ctx,
493                                                  const char *domain,
494                                                  const struct auth_usersupplied_info *user_info, 
495                                                  struct auth_serversupplied_info **server_info)
496 {
497         NTSTATUS nt_status;
498         const char *account_name = user_info->account_name;
499         struct ldb_message **msgs;
500         struct ldb_message **domain_msgs;
501         void *sam_ctx;
502         DATA_BLOB user_sess_key, lm_sess_key;
503
504         if (!account_name || !*account_name) {
505                 /* 'not for me' */
506                 return NT_STATUS_NOT_IMPLEMENTED;
507         }
508
509         sam_ctx = samdb_connect(mem_ctx);
510         if (sam_ctx == NULL) {
511                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
512         }
513
514         nt_status = authsam_search_account(mem_ctx, sam_ctx, account_name, domain, &msgs, &domain_msgs);
515         NT_STATUS_NOT_OK_RETURN(nt_status);
516
517         nt_status = authsam_authenticate(ctx->auth_ctx, mem_ctx, sam_ctx, msgs, domain_msgs, user_info,
518                                          &user_sess_key, &lm_sess_key);
519         NT_STATUS_NOT_OK_RETURN(nt_status);
520
521         nt_status = authsam_make_server_info(mem_ctx, sam_ctx, msgs, domain_msgs,
522                                              user_sess_key, lm_sess_key,
523                                              server_info);
524         NT_STATUS_NOT_OK_RETURN(nt_status);
525
526         talloc_free(msgs);
527         talloc_free(domain_msgs);
528
529         return NT_STATUS_OK;
530 }
531
532 static NTSTATUS authsam_ignoredomain_check_password(struct auth_method_context *ctx,
533                                                     TALLOC_CTX *mem_ctx,
534                                                     const struct auth_usersupplied_info *user_info, 
535                                                     struct auth_serversupplied_info **server_info)
536 {
537         return authsam_check_password_internals(ctx, mem_ctx, NULL, user_info, server_info);
538 }
539
540 /****************************************************************************
541 Check SAM security (above) but with a few extra checks.
542 ****************************************************************************/
543 static NTSTATUS authsam_check_password(struct auth_method_context *ctx,
544                                        TALLOC_CTX *mem_ctx,
545                                        const struct auth_usersupplied_info *user_info, 
546                                        struct auth_serversupplied_info **server_info)
547 {
548         const char *domain;
549         BOOL is_local_name, is_my_domain;
550
551         is_local_name = is_myname(user_info->domain_name);
552         is_my_domain  = strequal(user_info->domain_name, lp_workgroup());
553
554         /* check whether or not we service this domain/workgroup name */
555         switch (lp_server_role()) {
556                 case ROLE_STANDALONE:
557                         domain = lp_netbios_name();
558                         break;
559                 case ROLE_DOMAIN_MEMBER:
560                         if (!is_local_name) {
561                                 DEBUG(6,("authsam_check_password: %s is not one of my local names (%s)\n",
562                                         user_info->domain_name, (lp_server_role() == ROLE_DOMAIN_MEMBER 
563                                         ? "ROLE_DOMAIN_MEMBER" : "ROLE_STANDALONE") ));
564                                 return NT_STATUS_NOT_IMPLEMENTED;
565                         }
566                         domain = lp_netbios_name();
567                         break;
568                 case ROLE_DOMAIN_PDC:
569                 case ROLE_DOMAIN_BDC:
570                         if (!is_local_name && !is_my_domain) {
571                                 DEBUG(6,("authsam_check_password: %s is not one of my local names or domain name (DC)\n",
572                                         user_info->domain_name));
573                                 return NT_STATUS_NOT_IMPLEMENTED;
574                         }
575                         domain = lp_workgroup();
576                         break;
577                 default:
578                         DEBUG(6,("authsam_check_password: lp_server_role() has an undefined value\n"));
579                         return NT_STATUS_NOT_IMPLEMENTED;
580         }
581
582         return authsam_check_password_internals(ctx, mem_ctx, domain, user_info, server_info);
583 }
584
585 static const struct auth_operations sam_ignoredomain_ops = {
586         .name           = "sam_ignoredomain",
587         .get_challenge  = auth_get_challenge_not_implemented,
588         .check_password = authsam_ignoredomain_check_password
589 };
590
591 static const struct auth_operations sam_ops = {
592         .name           = "sam",
593         .get_challenge  = auth_get_challenge_not_implemented,
594         .check_password = authsam_check_password
595 };
596
597 NTSTATUS auth_sam_init(void)
598 {
599         NTSTATUS ret;
600
601         ret = auth_register(&sam_ops);
602         if (!NT_STATUS_IS_OK(ret)) {
603                 DEBUG(0,("Failed to register 'sam' auth backend!\n"));
604                 return ret;
605         }
606
607         ret = auth_register(&sam_ignoredomain_ops);
608         if (!NT_STATUS_IS_OK(ret)) {
609                 DEBUG(0,("Failed to register 'sam_ignoredomain' auth backend!\n"));
610                 return ret;
611         }
612
613         return ret;
614 }