r6883: Move to what simo assures me is the 'correct' way to find the NetBIOS
[jelmer/samba4-debian.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_tmp;
183         struct ldb_message **msgs;
184         struct ldb_message **msgs_domain;
185
186         int ret;
187         int ret_domain;
188
189         const char *domain_dn = NULL;
190
191         const char *attrs[] = {"unicodePwd", "lmPwdHash", "ntPwdHash",
192                                "userAccountControl",
193                                "pwdLastSet",
194                                "accountExpires",
195                                "objectSid",
196                                "userWorkstations",
197                                
198                                /* required for server_info, not access control: */
199                                "sAMAccountName",
200                                "displayName",
201                                "scriptPath",
202                                "profilePath",
203                                "homeDirectory",
204                                "homeDrive",
205                                "lastLogon",
206                                "lastLogoff",
207                                "accountExpires",
208                                "badPwdCount",
209                                "logonCount",
210                                "primaryGroupID",
211                                NULL,
212         };
213
214         const char *domain_attrs[] =  {"nETBIOSName", "nCName"};
215
216         if (domain_name) {
217                 /* find the domain's DN */
218                 ret_domain = gendb_search(sam_ctx, mem_ctx, NULL, &msgs_domain, domain_attrs,
219                                           "(&(&(|(&(dnsRoot=%s)(nETBIOSName=*))(nETBIOSName=%s))(objectclass=crossRef))(ncName=*))", 
220                                           domain_name, domain_name);
221                 if (ret_domain == -1) {
222                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
223                 }
224
225                 if (ret_domain == 0) {
226                         DEBUG(3,("sam_search_user: Couldn't find domain [%s] in samdb.\n", 
227                                  domain_name));
228                         return NT_STATUS_NO_SUCH_USER;
229                 }
230
231                 if (ret_domain > 1) {
232                         DEBUG(0,("Found %d records matching domain [%s]\n", 
233                                  ret_domain, domain_name));
234                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
235                 }
236
237                 domain_dn = samdb_result_string(msgs_domain[0], "nCName", NULL);
238         }
239
240         /* pull the user attributes */
241         ret = gendb_search(sam_ctx, mem_ctx, domain_dn, &msgs, attrs,
242                            "(&(sAMAccountName=%s)(objectclass=user))", 
243                            account_name);
244         if (ret == -1) {
245                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
246         }
247
248         if (ret == 0) {
249                 DEBUG(3,("sam_search_user: Couldn't find user [%s] in samdb.\n", 
250                          account_name));
251                 return NT_STATUS_NO_SUCH_USER;
252         }
253
254         if (ret > 1) {
255                 DEBUG(0,("Found %d records matching user [%s]\n", ret, account_name));
256                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
257         }
258
259         if (!domain_name) {
260                 const char *domain_sid;
261
262                 domain_sid = samdb_result_sid_prefix(mem_ctx, msgs[0], "objectSid");
263                 if (!domain_sid) {
264                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
265                 }
266
267                 /* find the domain's DN */
268                 ret = gendb_search(sam_ctx, mem_ctx, NULL, &msgs_tmp, NULL,
269                                    "(&(objectSid=%s)(objectclass=domain))", 
270                                    domain_sid);
271                 if (ret == -1) {
272                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
273                 }
274                 
275                 if (ret == 0) {
276                         DEBUG(3,("check_sam_security: Couldn't find domain_sid [%s] in passdb file.\n",
277                                  domain_sid));
278                         return NT_STATUS_NO_SUCH_USER;
279                 }
280                 
281                 if (ret > 1) {
282                         DEBUG(0,("Found %d records matching domain_sid [%s]\n", 
283                                  ret, domain_sid));
284                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
285                 }
286
287                 ret_domain = gendb_search(sam_ctx, mem_ctx, NULL, &msgs_domain, domain_attrs,
288                                           "(nCName=%s)", msgs_tmp[0]->dn);
289
290                 if (ret_domain == -1) {
291                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
292                 }
293                 
294                 if (ret_domain == 0) {
295                         DEBUG(3,("check_sam_security: Couldn't find domain [%s] in passdb file.\n",
296                                  msgs_tmp[0]->dn));
297                         return NT_STATUS_NO_SUCH_USER;
298                 }
299                 
300                 if (ret_domain > 1) {
301                         DEBUG(0,("Found %d records matching domain [%s]\n", 
302                                  ret_domain, msgs_tmp[0]->dn));
303                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
304                 }
305
306         }
307
308         *ret_msgs = msgs;
309         *ret_msgs_domain = msgs_domain;
310         
311         return NT_STATUS_OK;
312 }
313
314 static NTSTATUS authsam_authenticate(const struct auth_context *auth_context, 
315                                      TALLOC_CTX *mem_ctx, void *sam_ctx, 
316                                      struct ldb_message **msgs,
317                                      struct ldb_message **msgs_domain,
318                                      const struct auth_usersupplied_info *user_info, 
319                                      DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key) 
320 {
321         uint16_t acct_flags;
322         const char *workstation_list;
323         NTTIME acct_expiry;
324         NTTIME must_change_time;
325         NTTIME last_set_time;
326         struct samr_Password *lm_pwd, *nt_pwd;
327         NTSTATUS nt_status;
328         const char *domain_dn = samdb_result_string(msgs_domain[0], "nCName", "");
329
330         acct_flags = samdb_result_acct_flags(msgs[0], "sAMAcctFlags");
331         
332         /* Quit if the account was locked out. */
333         if (acct_flags & ACB_AUTOLOCK) {
334                 DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", 
335                          user_info->account_name));
336                 return NT_STATUS_ACCOUNT_LOCKED_OUT;
337         }
338
339         nt_status = samdb_result_passwords(mem_ctx, msgs[0], &lm_pwd, &nt_pwd);
340         NT_STATUS_NOT_OK_RETURN(nt_status);
341
342         nt_status = authsam_password_ok(auth_context, mem_ctx, 
343                                         acct_flags, lm_pwd, nt_pwd,
344                                         user_info, user_sess_key, lm_sess_key);
345         NT_STATUS_NOT_OK_RETURN(nt_status);
346
347         acct_expiry = samdb_result_nttime(msgs[0], "accountExpires", 0);
348         must_change_time = samdb_result_force_password_change(sam_ctx, mem_ctx, 
349                                                               domain_dn, msgs[0], 
350                                                               "pwdLastSet");
351         last_set_time = samdb_result_nttime(msgs[0], "pwdLastSet", 0);
352
353         workstation_list = samdb_result_string(msgs[0], "userWorkstations", NULL);
354
355         nt_status = authsam_account_ok(mem_ctx, acct_flags, 
356                                        acct_expiry, 
357                                        must_change_time, 
358                                        last_set_time, 
359                                        workstation_list,
360                                        user_info);
361
362         return nt_status;
363 }
364
365 static NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, void *sam_ctx,
366                                          struct ldb_message **msgs,
367                                          struct ldb_message **msgs_domain,
368                                          DATA_BLOB user_sess_key, DATA_BLOB lm_sess_key,
369                                          struct auth_serversupplied_info **_server_info)
370 {
371         struct auth_serversupplied_info *server_info;
372         struct ldb_message **group_msgs;
373         int group_ret;
374         const char *group_attrs[3] = { "sAMAccountType", "objectSid", NULL }; 
375         /* find list of sids */
376         struct dom_sid **groupSIDs = NULL;
377         struct dom_sid *account_sid;
378         struct dom_sid *primary_group_sid;
379         const char *str, *ncname;
380         int i;
381         uint_t rid;
382         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
383
384         group_ret = gendb_search(sam_ctx,
385                                  tmp_ctx, NULL, &group_msgs, group_attrs,
386                                  "(&(member=%s)(sAMAccountType=*))", 
387                                  msgs[0]->dn);
388         if (group_ret == -1) {
389                 talloc_free(tmp_ctx);
390                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
391         }
392
393         server_info = talloc(mem_ctx, struct auth_serversupplied_info);
394         NT_STATUS_HAVE_NO_MEMORY(server_info);
395         
396         if (group_ret > 0) {
397                 groupSIDs = talloc_array(server_info, struct dom_sid *, group_ret);
398                 NT_STATUS_HAVE_NO_MEMORY(groupSIDs);
399         }
400
401         /* Need to unroll some nested groups, but not aliases */
402         for (i = 0; i < group_ret; i++) {
403                 str = ldb_msg_find_string(group_msgs[i], "objectSid", NULL);
404                 groupSIDs[i] = dom_sid_parse_talloc(groupSIDs, str);
405                 NT_STATUS_HAVE_NO_MEMORY(groupSIDs[i]);
406         }
407
408         talloc_free(tmp_ctx);
409
410         str = ldb_msg_find_string(msgs[0], "objectSid", NULL);
411         account_sid = dom_sid_parse_talloc(server_info, str);
412         NT_STATUS_HAVE_NO_MEMORY(account_sid);
413
414         primary_group_sid = dom_sid_dup(server_info, account_sid);
415         NT_STATUS_HAVE_NO_MEMORY(primary_group_sid);
416
417         rid = samdb_result_uint(msgs[0], "primaryGroupID", ~0);
418         if (rid == ~0) {
419                 if (group_ret > 0) {
420                         primary_group_sid = groupSIDs[0];
421                 } else {
422                         primary_group_sid = NULL;
423                 }
424         } else {
425                 primary_group_sid->sub_auths[primary_group_sid->num_auths-1] = rid;
426         }
427
428         server_info->account_sid = account_sid;
429         server_info->primary_group_sid = primary_group_sid;
430         
431         server_info->n_domain_groups = group_ret;
432         server_info->domain_groups = groupSIDs;
433
434         server_info->account_name = talloc_reference(server_info, samdb_result_string(msgs[0], "sAMAccountName", NULL));
435
436         server_info->domain_name = talloc_reference(server_info, samdb_result_string(msgs_domain[0], "nETBIOSName", NULL));
437
438         str = samdb_result_string(msgs[0], "displayName", "");
439         server_info->full_name = talloc_strdup(server_info, str);
440         NT_STATUS_HAVE_NO_MEMORY(server_info->full_name);
441
442         str = samdb_result_string(msgs[0], "scriptPath", "");
443         server_info->logon_script = talloc_strdup(server_info, str);
444         NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script);
445
446         str = samdb_result_string(msgs[0], "profilePath", "");
447         server_info->profile_path = talloc_strdup(server_info, str);
448         NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path);
449
450         str = samdb_result_string(msgs[0], "homeDirectory", "");
451         server_info->home_directory = talloc_strdup(server_info, str);
452         NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory);
453
454         str = samdb_result_string(msgs[0], "homeDrive", "");
455         server_info->home_drive = talloc_strdup(server_info, str);
456         NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive);
457
458         server_info->last_logon = samdb_result_nttime(msgs[0], "lastLogon", 0);
459         server_info->last_logoff = samdb_result_nttime(msgs[0], "lastLogoff", 0);
460         server_info->acct_expiry = samdb_result_nttime(msgs[0], "accountExpires", 0);
461         server_info->last_password_change = samdb_result_nttime(msgs[0], "pwdLastSet", 0);
462
463         ncname = samdb_result_string(msgs_domain[0], "nCName", "");
464
465         server_info->allow_password_change = samdb_result_allow_password_change(sam_ctx, mem_ctx, 
466                                                         ncname, msgs[0], "pwdLastSet");
467         server_info->force_password_change = samdb_result_force_password_change(sam_ctx, mem_ctx, 
468                                                         ncname, msgs[0], "pwdLastSet");
469
470         server_info->logon_count = samdb_result_uint(msgs[0], "logonCount", 0);
471         server_info->bad_password_count = samdb_result_uint(msgs[0], "badPwdCount", 0);
472
473         server_info->acct_flags = samdb_result_acct_flags(msgs[0], "userAccountControl");
474
475         server_info->user_session_key = user_sess_key;
476         server_info->lm_session_key = lm_sess_key;
477
478         server_info->authenticated = True;
479
480         *_server_info = server_info;
481
482         return NT_STATUS_OK;
483 }
484
485 NTSTATUS sam_get_server_info(TALLOC_CTX *mem_ctx, const char *account_name, const char *domain_name,
486                              DATA_BLOB user_sess_key, DATA_BLOB lm_sess_key,
487                              struct auth_serversupplied_info **server_info)
488 {
489         NTSTATUS nt_status;
490
491         struct ldb_message **msgs;
492         struct ldb_message **domain_msgs;
493         void *sam_ctx;
494
495         sam_ctx = samdb_connect(mem_ctx);
496         if (sam_ctx == NULL) {
497                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
498         }
499
500         nt_status = authsam_search_account(mem_ctx, sam_ctx, account_name, domain_name, &msgs, &domain_msgs);
501         NT_STATUS_NOT_OK_RETURN(nt_status);
502
503         nt_status = authsam_make_server_info(mem_ctx, sam_ctx, msgs, domain_msgs,
504                                              user_sess_key, lm_sess_key,
505                                              server_info);
506         NT_STATUS_NOT_OK_RETURN(nt_status);
507
508         talloc_free(msgs);
509         talloc_free(domain_msgs);
510
511         return NT_STATUS_OK;
512 }
513
514 static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx,
515                                                  TALLOC_CTX *mem_ctx,
516                                                  const char *domain,
517                                                  const struct auth_usersupplied_info *user_info, 
518                                                  struct auth_serversupplied_info **server_info)
519 {
520         NTSTATUS nt_status;
521         const char *account_name = user_info->account_name;
522         struct ldb_message **msgs;
523         struct ldb_message **domain_msgs;
524         void *sam_ctx;
525         DATA_BLOB user_sess_key, lm_sess_key;
526
527         if (!account_name || !*account_name) {
528                 /* 'not for me' */
529                 return NT_STATUS_NOT_IMPLEMENTED;
530         }
531
532         sam_ctx = samdb_connect(mem_ctx);
533         if (sam_ctx == NULL) {
534                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
535         }
536
537         nt_status = authsam_search_account(mem_ctx, sam_ctx, account_name, domain, &msgs, &domain_msgs);
538         NT_STATUS_NOT_OK_RETURN(nt_status);
539
540         nt_status = authsam_authenticate(ctx->auth_ctx, mem_ctx, sam_ctx, msgs, domain_msgs, user_info,
541                                          &user_sess_key, &lm_sess_key);
542         NT_STATUS_NOT_OK_RETURN(nt_status);
543
544         nt_status = authsam_make_server_info(mem_ctx, sam_ctx, msgs, domain_msgs,
545                                              user_sess_key, lm_sess_key,
546                                              server_info);
547         NT_STATUS_NOT_OK_RETURN(nt_status);
548
549         talloc_free(msgs);
550         talloc_free(domain_msgs);
551
552         return NT_STATUS_OK;
553 }
554
555 static NTSTATUS authsam_ignoredomain_check_password(struct auth_method_context *ctx,
556                                                     TALLOC_CTX *mem_ctx,
557                                                     const struct auth_usersupplied_info *user_info, 
558                                                     struct auth_serversupplied_info **server_info)
559 {
560         return authsam_check_password_internals(ctx, mem_ctx, NULL, user_info, server_info);
561 }
562
563 /****************************************************************************
564 Check SAM security (above) but with a few extra checks.
565 ****************************************************************************/
566 static NTSTATUS authsam_check_password(struct auth_method_context *ctx,
567                                        TALLOC_CTX *mem_ctx,
568                                        const struct auth_usersupplied_info *user_info, 
569                                        struct auth_serversupplied_info **server_info)
570 {
571         const char *domain;
572         BOOL is_local_name, is_my_domain;
573
574         is_local_name = is_myname(user_info->domain_name);
575         is_my_domain  = strequal(user_info->domain_name, lp_workgroup());
576
577         /* check whether or not we service this domain/workgroup name */
578         switch (lp_server_role()) {
579                 case ROLE_STANDALONE:
580                         domain = lp_netbios_name();
581                         break;
582                 case ROLE_DOMAIN_MEMBER:
583                         if (!is_local_name) {
584                                 DEBUG(6,("authsam_check_password: %s is not one of my local names (%s)\n",
585                                         user_info->domain_name, (lp_server_role() == ROLE_DOMAIN_MEMBER 
586                                         ? "ROLE_DOMAIN_MEMBER" : "ROLE_STANDALONE") ));
587                                 return NT_STATUS_NOT_IMPLEMENTED;
588                         }
589                         domain = lp_netbios_name();
590                         break;
591                 case ROLE_DOMAIN_PDC:
592                 case ROLE_DOMAIN_BDC:
593                         if (!is_local_name && !is_my_domain) {
594                                 DEBUG(6,("authsam_check_password: %s is not one of my local names or domain name (DC)\n",
595                                         user_info->domain_name));
596                                 return NT_STATUS_NOT_IMPLEMENTED;
597                         }
598                         domain = lp_workgroup();
599                         break;
600                 default:
601                         DEBUG(6,("authsam_check_password: lp_server_role() has an undefined value\n"));
602                         return NT_STATUS_NOT_IMPLEMENTED;
603         }
604
605         return authsam_check_password_internals(ctx, mem_ctx, domain, user_info, server_info);
606 }
607
608 static const struct auth_operations sam_ignoredomain_ops = {
609         .name           = "sam_ignoredomain",
610         .get_challenge  = auth_get_challenge_not_implemented,
611         .check_password = authsam_ignoredomain_check_password
612 };
613
614 static const struct auth_operations sam_ops = {
615         .name           = "sam",
616         .get_challenge  = auth_get_challenge_not_implemented,
617         .check_password = authsam_check_password
618 };
619
620 NTSTATUS auth_sam_init(void)
621 {
622         NTSTATUS ret;
623
624         ret = auth_register(&sam_ops);
625         if (!NT_STATUS_IS_OK(ret)) {
626                 DEBUG(0,("Failed to register 'sam' auth backend!\n"));
627                 return ret;
628         }
629
630         ret = auth_register(&sam_ignoredomain_ops);
631         if (!NT_STATUS_IS_OK(ret)) {
632                 DEBUG(0,("Failed to register 'sam_ignoredomain' auth backend!\n"));
633                 return ret;
634         }
635
636         return ret;
637 }