sync'ing up for 3.0alpha20 release
[Samba.git] / source / passdb / pdb_nisplus.c
blob484e8986e42f57fa64ddd01fd04df6b3e8332014
2 /*
3 * NIS+ Passdb Backend
4 * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995.
5 * Copyright (C) Benny Holmgren 1998 <bigfoot@astrakan.hgs.se>
6 * Copyright (C) Luke Kenneth Casson Leighton 1996-1998.
7 * Copyright (C) Toomas Soome <tsoome@ut.ee> 2001
8 * Copyright (C) Jelmer Vernooij 2002
9 *
10 * This program is free software; you can redistribute it and/or modify it under
11 * the terms of the GNU General Public License as published by the Free
12 * Software Foundation; either version 2 of the License, or (at your option)
13 * any later version.
15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * more details.
20 * You should have received a copy of the GNU General Public License along with
21 * this program; if not, write to the Free Software Foundation, Inc., 675
22 * Mass Ave, Cambridge, MA 02139, USA.
25 #include "includes.h"
27 #ifdef WITH_NISPLUS_SAM
29 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
32 * The following lines are needed due to buggy include files
33 * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
34 * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
35 * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
36 * an enum in /usr/include/rpcsvc/nis.h.
40 #if defined(GROUP)
41 #undef GROUP
42 #endif
44 #if defined(GROUP_OBJ)
45 #undef GROUP_OBJ
46 #endif
48 #endif
50 #include <rpcsvc/nis.h>
52 /***************************************************************
54 the fields for the NIS+ table, generated from mknissmbpwtbl.sh, are:
56 name=S,nogw=r
57 uid=S,nogw=r
58 user_rid=S,nogw=r
59 smb_grpid=,nw+r
60 group_rid=,nw+r
61 acb=,nw+r
63 lmpwd=C,nw=,g=r,o=rm
64 ntpwd=C,nw=,g=r,o=rm
66 logon_t=,nw+r
67 logoff_t=,nw+r
68 kick_t=,nw+r
69 pwdlset_t=,nw+r
70 pwdlchg_t=,nw+r
71 pwdmchg_t=,nw+r
73 full_name=,nw+r
74 home_dir=,nw+r
75 dir_drive=,nw+r
76 logon_script=,nw+r
77 profile_path=,nw+r
78 acct_desc=,nw+r
79 workstations=,nw+r
81 hours=,nw+r
83 ****************************************************************/
85 #define NPF_NAME 0
86 #define NPF_UID 1
87 #define NPF_USER_RID 2
88 #define NPF_SMB_GRPID 3
89 #define NPF_GROUP_RID 4
90 #define NPF_ACB 5
91 #define NPF_LMPWD 6
92 #define NPF_NTPWD 7
93 #define NPF_LOGON_T 8
94 #define NPF_LOGOFF_T 9
95 #define NPF_KICK_T 10
96 #define NPF_PWDLSET_T 11
97 #define NPF_PWDCCHG_T 12
98 #define NPF_PWDMCHG_T 13
99 #define NPF_FULL_NAME 14
100 #define NPF_HOME_DIR 15
101 #define NPF_DIR_DRIVE 16
102 #define NPF_LOGON_SCRIPT 17
103 #define NPF_PROFILE_PATH 18
104 #define NPF_ACCT_DESC 19
105 #define NPF_WORKSTATIONS 20
106 #define NPF_HOURS 21
108 struct nisplus_private_info {
109 nis_result *result;
110 int enum_entry;
111 char *location;
114 static char *make_nisname_from_user_rid (uint32 rid, char *pfile);
115 static char *make_nisname_from_name (const char *user_name, char *pfile);
116 static void get_single_attribute (const nis_object * new_obj, int col,
117 char *val, int len);;
118 static BOOL make_sam_from_nisp_object (SAM_ACCOUNT * pw_buf,
119 const nis_object * obj);
120 static BOOL make_sam_from_nisresult (SAM_ACCOUNT * pw_buf,
121 const nis_result * result);;
122 static void set_single_attribute (nis_object * new_obj, int col,
123 const char *val, int len, int flags);
124 static BOOL init_nisp_from_sam (nis_object * obj, const SAM_ACCOUNT * sampass,
125 nis_object * old);
126 static nis_result *nisp_get_nis_list (const char *nisname,
127 unsigned int flags);
129 /***************************************************************
130 Start enumeration of the passwd list.
131 ****************************************************************/
133 static BOOL nisplussam_setsampwent (struct pdb_methods *methods, BOOL update)
135 struct nisplus_private_info *private =
136 (struct nisplus_private_info *) methods->private_data;
138 char *sp;
139 pstring pfiletmp;
141 if ((sp = strrchr (private->location, '/')))
142 safe_strcpy (pfiletmp, sp + 1, sizeof (pfiletmp) - 1);
143 else
144 safe_strcpy (pfiletmp, p, sizeof (pfiletmp) - 1);
145 safe_strcat (pfiletmp, ".org_dir",
146 sizeof (pfiletmp) - strlen (pfiletmp) - 1);
148 pdb_endsampwent (); /* just in case */
149 global_nisp_ent->result = nisp_get_nis_list (pfiletmp, 0);
150 global_nisp_ent->enum_entry = 0;
151 return global_nisp_ent->result != NULL ? True : False;
154 /***************************************************************
155 End enumeration of the passwd list.
156 ****************************************************************/
158 static void nisplussam_endsampwent (struct pdb_methods *methods)
160 struct nisplus_private_info *global_nisp_ent =
161 (struct nisplus_private_info *) methods->private_data;
162 if (global_nisp_ent->result)
163 nis_freeresult (global_nisp_ent->result);
164 global_nisp_ent->result = NULL;
165 global_nisp_ent->enum_entry = 0;
168 /*****************************************************************
169 Get one SAM_ACCOUNT from the list (next in line)
170 *****************************************************************/
172 static BOOL nisplussam_getsampwent (struct pdb_methods *methods,
173 SAM_ACCOUNT * user)
176 struct nisplus_private_info *global_nisp_ent =
177 (struct nisplus_private_info *) methods->private_data;
178 int enum_entry = (int) (global_nisp_ent->enum_entry);
179 nis_result *result = global_nisp_ent->result;
181 if (user == NULL) {
182 DEBUG (0, ("SAM_ACCOUNT is NULL.\n"));
183 return False;
186 if (result == NULL ||
187 enum_entry < 0 || enum_entry >= (NIS_RES_NUMOBJ (result) - 1)) {
188 return False;
191 if (!make_sam_from_nisp_object
192 (user, &NIS_RES_OBJECT (result)[enum_entry])) {
193 DEBUG (0, ("Bad SAM_ACCOUNT entry returned from NIS+!\n"));
194 return False;
196 (int) (global_nisp_ent->enum_entry)++;
197 return True;
198 DEBUG (10, ("nisplussam_getsampwent called\n"));
199 return False;
202 /******************************************************************
203 Lookup a name in the SAM database
204 ******************************************************************/
206 static BOOL nisplussam_getsampwnam (struct pdb_methods *methods,
207 SAM_ACCOUNT * user, const char *sname)
209 /* Static buffers we will return. */
210 nis_result *result = NULL;
211 pstring nisname;
212 BOOL ret;
213 struct nisplus_private_info *private =
214 (struct nisplus_private_info *) methods->private_data;
216 if (!private->location || !(*private->location)) {
217 DEBUG (0, ("No SMB password file set\n"));
218 return False;
220 if (strrchr (private->location, '/'))
221 private->location = strrchr (private->location, '/') + 1;
223 slprintf (nisname, sizeof (nisname) - 1, "[name=%s],%s.org_dir",
224 sname, private->location);
225 DEBUG (10, ("search by nisname: %s\n", nisname));
227 /* Search the table. */
229 if (!(result = nisp_get_nis_list (nisname, 0))) {
230 return False;
233 ret = make_sam_from_nisresult (user, result);
234 nis_freeresult (result);
236 return ret;
238 DEBUG (10, ("nisplussam_getsampwnam called\n"));
239 return False;
242 /***************************************************************************
243 Search by sid
244 **************************************************************************/
246 static BOOL nisplussam_getsampwrid (struct pdb_methods *methods,
247 SAM_ACCOUNT * user, uint32 rid)
249 nis_result *result;
250 char *nisname;
251 BOOL ret;
252 char *sp;
253 pstring pfiletmp;
254 struct nisplus_private_info *private =
255 (struct nisplus_private_info *) methods->private_data;
257 if (!private->location || !(*private->location)) {
258 DEBUG (0, ("no SMB password file set\n"));
259 return False;
262 if ((sp = strrchr (private->location, '/')))
263 safe_strcpy (pfiletmp, sp + 1, sizeof (pfiletmp) - 1);
264 else
265 safe_strcpy (pfiletmp, private->location, sizeof (pfiletmp) - 1);
266 safe_strcat (pfiletmp, ".org_dir",
267 sizeof (pfiletmp) - strlen (pfiletmp) - 1);
269 nisname = make_nisname_from_user_rid (rid, pfiletmp);
271 DEBUG (10, ("search by rid: %s\n", nisname));
273 /* Search the table. */
275 if (!(result = nisp_get_nis_list (nisname, 0))) {
276 return False;
279 ret = make_sam_from_nisresult (user, result);
280 nis_freeresult (result);
282 return ret;
285 static BOOL nisplussam_getsampwsid (struct pdb_methods *methods,
286 SAM_ACCOUNT * user, const DOM_SID * sid)
288 uint32 rid;
290 if (!sid_peek_check_rid (get_global_sam_sid (), sid, &rid))
291 return False;
292 return nisplussam_getsampwrid (methods, user, rid);
297 /***************************************************************************
298 Delete a SAM_ACCOUNT
299 ****************************************************************************/
301 static BOOL nisplussam_delete_sam_account (struct pdb_methods *methods,
302 SAM_ACCOUNT * user)
304 const char *sname;
305 pstring nisname;
306 nis_result *result, *delresult;
307 nis_object *obj;
308 struct nisplus_private_info *private =
309 (struct nisplus_private_info *) methods->private_data;
311 if (!user) {
312 DEBUG (0, ("no SAM_ACCOUNT specified!\n"));
313 return False;
316 sname = pdb_get_username (user);
318 if (!private->location || !(*private->location)) {
319 DEBUG (0, ("no SMB password file set\n"));
320 return False;
323 if (strrchr (private->location, '/'))
324 private->location = strrchr (private->location, '/') + 1;
326 slprintf (nisname, sizeof (nisname) - 1, "[name=%s],%s.org_dir",
327 sname, private->location);
329 /* Search the table. */
331 if (!(result = nisp_get_nis_list (nisname,
332 MASTER_ONLY | FOLLOW_LINKS |
333 FOLLOW_PATH | EXPAND_NAME |
334 HARD_LOOKUP))) {
335 return False;
338 if (result->status != NIS_SUCCESS || NIS_RES_NUMOBJ (result) <= 0) {
339 /* User not found. */
340 DEBUG (0, ("user not found in NIS+\n"));
341 nis_freeresult (result);
342 return False;
345 obj = NIS_RES_OBJECT (result);
346 slprintf (nisname, sizeof (nisname) - 1, "[name=%s],%s.%s", sname,
347 obj->zo_name, obj->zo_domain);
349 DEBUG (10, ("removing name: %s\n", nisname));
350 delresult = nis_remove_entry (nisname, obj,
351 MASTER_ONLY | REM_MULTIPLE | ALL_RESULTS
352 | FOLLOW_PATH | EXPAND_NAME |
353 HARD_LOOKUP);
355 nis_freeresult (result);
357 if (delresult->status != NIS_SUCCESS) {
358 DEBUG (0, ("NIS+ table update failed: %s %s\n",
359 nisname, nis_sperrno (delresult->status)));
360 nis_freeresult (delresult);
361 return False;
363 nis_freeresult (delresult);
364 return True;
365 DEBUG (10, ("nisplussam_delete_sam_account called\n"));
366 return False;
369 /***************************************************************************
370 Modifies an existing SAM_ACCOUNT
371 ****************************************************************************/
373 static BOOL nisplussam_update_sam_account (struct pdb_methods *methods,
374 SAM_ACCOUNT * newpwd)
376 nis_result *result, *addresult;
377 nis_object *obj;
378 nis_object new_obj;
379 entry_col *ecol;
380 int ta_maxcol;
381 struct nisplus_private_info *private =
382 (struct nisplus_private_info *) methods->private_data;
383 pstring nisname;
385 if (!private->location || !(*private->location)) {
386 DEBUG (0, ("no SMB password file set\n"));
387 return False;
389 if (strrchr (private->location, '/'))
390 private->location = strrchr (private->location, '/') + 1;
392 slprintf (nisname, sizeof (nisname) - 1, "[name=%s],%s.org_dir",
393 pdb_get_username (newpwd), private->location);
395 DEBUG (10, ("search by name: %s\n", nisname));
397 /* Search the table. */
399 if (!
400 (result =
401 nisp_get_nis_list (nisname,
402 MASTER_ONLY | FOLLOW_LINKS | FOLLOW_PATH |
403 EXPAND_NAME | HARD_LOOKUP))) {
404 return False;
407 if (result->status != NIS_SUCCESS || NIS_RES_NUMOBJ (result) <= 0) {
408 /* User not found. */
409 DEBUG (0, ("user not found in NIS+\n"));
410 nis_freeresult (result);
411 return False;
414 obj = NIS_RES_OBJECT (result);
415 DEBUG (6, ("entry found in %s\n", obj->zo_domain));
417 /* we must create new stub object with EN_MODIFIED flag.
418 this is because obj from result is going to be freed and
419 we do not want to break it or cause memory leaks or corruption.
422 memmove ((char *) &new_obj, obj, sizeof (new_obj));
423 ta_maxcol = obj->TA_data.ta_maxcol;
425 if (!(ecol = (entry_col *) malloc (ta_maxcol * sizeof (entry_col)))) {
426 DEBUG (0, ("memory allocation failure\n"));
427 nis_freeresult (result);
428 return False;
431 memmove ((char *) ecol, obj->EN_data.en_cols.en_cols_val,
432 ta_maxcol * sizeof (entry_col));
433 new_obj.EN_data.en_cols.en_cols_val = ecol;
434 new_obj.EN_data.en_cols.en_cols_len = ta_maxcol;
436 if (init_nisp_from_sam (&new_obj, newpwd, obj) == True) {
437 slprintf (nisname, sizeof (nisname) - 1, "[name=%s],%s.%s",
438 pdb_get_username (newpwd), private->location, obj->zo_domain);
440 DEBUG (10, ("NIS+ table update: %s\n", nisname));
441 addresult =
442 nis_modify_entry (nisname, &new_obj,
443 MOD_SAMEOBJ | FOLLOW_PATH |
444 EXPAND_NAME | HARD_LOOKUP);
446 if (addresult->status != NIS_SUCCESS) {
447 DEBUG (0, ("NIS+ table update failed: %s %s\n",
448 nisname, nis_sperrno (addresult->status)));
449 nis_freeresult (addresult);
450 nis_freeresult (result);
451 free (ecol);
452 return False;
455 DEBUG (6, ("password changed\n"));
456 nis_freeresult (addresult);
457 } else {
458 DEBUG (6, ("nothing to change!\n"));
461 free (ecol);
462 nis_freeresult (result);
464 return True;
467 /***************************************************************************
468 Adds an existing SAM_ACCOUNT
469 ****************************************************************************/
471 static BOOL nisplussam_add_sam_account (struct pdb_methods *methods,
472 SAM_ACCOUNT * newpwd)
474 int local_user = 0;
475 char *pfile;
476 pstring pfiletmp;
477 char *nisname;
478 nis_result *result = NULL, *tblresult = NULL;
479 nis_object new_obj;
480 entry_col *ecol;
481 int ta_maxcol;
484 * 1. find user domain.
485 * a. try nis search in passwd.org_dir - if found use domain from result.
486 * b. try getpwnam. this may be needed if user is defined
487 * in /etc/passwd file (or elsewere) and not in passwd.org_dir.
488 * if found, use host default domain.
489 * c. exit with False - no such user.
491 * 2. add user
492 * a. find smbpasswd table
493 * search pfile in user domain if not found, try host default
494 * domain.
495 * b. smbpasswd domain is found, fill data and add entry.
497 * pfile should contain ONLY table name, org_dir will be concated.
498 * so, at first we will clear path prefix from pfile, and
499 * then we will use pfiletmp as playground to put together full
500 * nisname string.
501 * such approach will make it possible to specify samba private dir
502 * AND still use NIS+ table. as all domain related data is normally
503 * stored in org_dir.DOMAIN, this should be ok do do.
506 pfile = private->location;
507 if (strrchr (pfile, '/'))
508 pfile = strrchr (pfile, '/') + 1;
511 * Check if user is already there.
513 safe_strcpy (pfiletmp, pfile, sizeof (pfiletmp) - 1);
514 safe_strcat (pfiletmp, ".org_dir",
515 sizeof (pfiletmp) - strlen (pfiletmp) - 1);
517 if (pdb_get_username (newpwd) != NULL) {
518 nisname = make_nisname_from_name (pdb_get_username (newpwd),
519 pfiletmp);
520 } else {
521 return False;
524 if (!
525 (result =
526 nisp_get_nis_list (nisname,
527 MASTER_ONLY | FOLLOW_LINKS | FOLLOW_PATH |
528 EXPAND_NAME | HARD_LOOKUP))) {
529 return False;
531 if (result->status != NIS_SUCCESS && result->status != NIS_NOTFOUND) {
532 DEBUG (3, ("nis_list failure: %s: %s\n",
533 nisname, nis_sperrno (result->status)));
534 nis_freeresult (result);
535 return False;
538 if (result->status == NIS_SUCCESS && NIS_RES_NUMOBJ (result) > 0) {
539 DEBUG (3, ("User already exists in NIS+ password db: %s\n",
540 pfile));
541 nis_freeresult (result);
542 return False;
545 nis_freeresult (result); /* no such user, free results */
548 * check for user in unix password database. we need this to get
549 * domain, where smbpasswd entry should be stored.
552 nisname = make_nisname_from_name (pdb_get_username (newpwd),
553 "passwd.org_dir");
555 result = nisp_get_nis_list (nisname,
556 MASTER_ONLY | FOLLOW_LINKS | FOLLOW_PATH |
557 EXPAND_NAME | HARD_LOOKUP);
559 if (result->status != NIS_SUCCESS || NIS_RES_NUMOBJ (result) <= 0) {
560 struct passwd *passwd;
562 DEBUG (3, ("nis_list failure: %s: %s\n",
563 nisname, nis_sperrno (result->status)));
564 nis_freeresult (result);
566 if (!(passwd = getpwnam_alloc (pdb_get_username (newpwd)))) {
567 /* no such user in system! */
568 return False;
570 passwd_free (&passwd);
573 * user is defined, but not in passwd.org_dir.
575 local_user = 1;
576 } else {
577 safe_strcpy (pfiletmp, pfile, sizeof (pfiletmp) - 1);
578 safe_strcat (pfiletmp, ".",
579 sizeof (pfiletmp) - strlen (pfiletmp) - 1);
580 safe_strcat (pfiletmp, NIS_RES_OBJECT (result)->zo_domain,
581 sizeof (pfiletmp) - strlen (pfiletmp) - 1);
582 nis_freeresult (result); /* not needed any more */
584 tblresult = nisp_get_nis_list (pfiletmp,
585 MASTER_ONLY | FOLLOW_LINKS |
586 FOLLOW_PATH | EXPAND_NAME |
587 HARD_LOOKUP);
590 if (local_user || tblresult->status != NIS_SUCCESS) {
592 * no user domain or
593 * smbpasswd table not found in user domain, fallback to
594 * default domain.
596 if (!local_user) /* free previous failed search result */
597 nis_freeresult (tblresult);
599 safe_strcpy (pfiletmp, pfile, sizeof (pfiletmp) - 1);
600 safe_strcat (pfiletmp, ".org_dir",
601 sizeof (pfiletmp) - strlen (pfiletmp) - 1);
602 tblresult = nis_lookup (pfiletmp, MASTER_ONLY | FOLLOW_LINKS |
603 FOLLOW_PATH | EXPAND_NAME |
604 HARD_LOOKUP);
605 if (tblresult->status != NIS_SUCCESS) {
606 /* still nothing. bail out */
607 nis_freeresult (tblresult);
608 DEBUG (3, ("nis_lookup failure: %s\n",
609 nis_sperrno (tblresult->status)));
610 return False;
612 /* we need full name for nis_add_entry() */
613 safe_strcpy (pfiletmp, pfile, sizeof (pfiletmp) - 1);
614 safe_strcat (pfiletmp, ".",
615 sizeof (pfiletmp) - strlen (pfiletmp) - 1);
616 safe_strcat (pfiletmp, NIS_RES_OBJECT (tblresult)->zo_domain,
617 sizeof (pfiletmp) - strlen (pfiletmp) - 1);
620 memset ((char *) &new_obj, 0, sizeof (new_obj));
621 /* fill entry headers */
622 /* we do not free these. */
623 new_obj.zo_name = NIS_RES_OBJECT (tblresult)->zo_name;
624 new_obj.zo_owner = NIS_RES_OBJECT (tblresult)->zo_owner;
625 new_obj.zo_group = NIS_RES_OBJECT (tblresult)->zo_group;
626 new_obj.zo_domain = NIS_RES_OBJECT (tblresult)->zo_domain;
627 /* uints */
628 new_obj.zo_access = NIS_RES_OBJECT (tblresult)->zo_access;
629 new_obj.zo_ttl = NIS_RES_OBJECT (tblresult)->zo_ttl;
631 new_obj.zo_data.zo_type = ENTRY_OBJ;
632 new_obj.EN_data.en_type = NIS_RES_OBJECT (tblresult)->TA_data.ta_type;
634 ta_maxcol = NIS_RES_OBJECT (tblresult)->TA_data.ta_maxcol;
636 if (!(ecol = (entry_col *) malloc (ta_maxcol * sizeof (entry_col)))) {
637 DEBUG (0, ("memory allocation failure\n"));
638 nis_freeresult (tblresult);
639 return False;
642 memset ((char *) ecol, 0, ta_maxcol * sizeof (entry_col));
643 new_obj.EN_data.en_cols.en_cols_val = ecol;
644 new_obj.EN_data.en_cols.en_cols_len = ta_maxcol;
646 init_nisp_from_sam (&new_obj, newpwd, NULL);
648 DEBUG (10, ("add NIS+ entry: %s\n", nisname));
649 result = nis_add_entry (pfiletmp, &new_obj, 0);
651 free (ecol); /* free allocated entry space */
653 if (result->status != NIS_SUCCESS) {
654 DEBUG (3, ("NIS+ table update failed: %s,%s\n",
655 nisname, nis_sperrno (result->status)));
656 nis_freeresult (tblresult);
657 nis_freeresult (result);
658 return False;
661 nis_freeresult (tblresult);
662 nis_freeresult (result);
664 return True;
667 /***************************************************************
668 make_nisname_from_user_rid
669 ****************************************************************/
670 static char *make_nisname_from_user_rid (uint32 rid, char *pfile)
672 static pstring nisname;
674 safe_strcpy (nisname, "[user_rid=", sizeof (nisname) - 1);
675 slprintf (nisname, sizeof (nisname) - 1, "%s%d", nisname, rid);
676 safe_strcat (nisname, "],", sizeof (nisname) - strlen (nisname) - 1);
677 safe_strcat (nisname, pfile, sizeof (nisname) - strlen (nisname) - 1);
679 return nisname;
682 /***************************************************************
683 make_nisname_from_name
684 ****************************************************************/
685 static char *make_nisname_from_name (const char *user_name, char *pfile)
687 static pstring nisname;
689 safe_strcpy (nisname, "[name=", sizeof (nisname) - 1);
690 safe_strcat (nisname, user_name,
691 sizeof (nisname) - strlen (nisname) - 1);
692 safe_strcat (nisname, "],", sizeof (nisname) - strlen (nisname) - 1);
693 safe_strcat (nisname, pfile, sizeof (nisname) - strlen (nisname) - 1);
695 return nisname;
698 /*************************************************************************
699 gets a NIS+ attribute
700 *************************************************************************/
701 static void get_single_attribute (const nis_object * new_obj, int col,
702 char *val, int len)
704 int entry_len;
706 if (new_obj == NULL || val == NULL)
707 return;
709 entry_len = ENTRY_LEN (new_obj, col);
710 if (len > entry_len) {
711 len = entry_len;
714 safe_strcpy (val, ENTRY_VAL (new_obj, col), len - 1);
717 /************************************************************************
718 makes a struct sam_passwd from a NIS+ object.
719 ************************************************************************/
720 static BOOL make_sam_from_nisp_object (SAM_ACCOUNT * pw_buf,
721 const nis_object * obj)
723 char *ptr;
724 pstring full_name; /* this must be translated to dos code page */
725 pstring acct_desc; /* this must be translated to dos code page */
726 pstring home_dir; /* set default value from smb.conf for user */
727 pstring home_drive; /* set default value from smb.conf for user */
728 pstring logon_script; /* set default value from smb.conf for user */
729 pstring profile_path; /* set default value from smb.conf for user */
730 pstring hours;
731 int hours_len;
732 unsigned char smbpwd[16];
733 unsigned char smbntpwd[16];
737 * time values. note: this code assumes 32bit time_t!
740 /* Don't change these timestamp settings without a good reason. They are
741 important for NT member server compatibility. */
743 pdb_set_logon_time (pw_buf, (time_t) 0, True);
744 ptr = (uchar *) ENTRY_VAL (obj, NPF_LOGON_T);
745 if (ptr && *ptr && (StrnCaseCmp (ptr, "LNT-", 4) == 0)) {
746 int i;
748 ptr += 4;
749 for (i = 0; i < 8; i++) {
750 if (ptr[i] == '\0' || !isxdigit (ptr[i]))
751 break;
753 if (i == 8) {
754 pdb_set_logon_time (pw_buf,
755 (time_t) strtol (ptr, NULL, 16),
756 True);
760 pdb_set_logoff_time (pw_buf, get_time_t_max (), True);
761 ptr = (uchar *) ENTRY_VAL (obj, NPF_LOGOFF_T);
762 if (ptr && *ptr && (StrnCaseCmp (ptr, "LOT-", 4) == 0)) {
763 int i;
765 ptr += 4;
766 for (i = 0; i < 8; i++) {
767 if (ptr[i] == '\0' || !isxdigit (ptr[i]))
768 break;
770 if (i == 8) {
771 pdb_set_logoff_time (pw_buf,
772 (time_t) strtol (ptr, NULL, 16),
773 True);
777 pdb_set_kickoff_time (pw_buf, get_time_t_max (), True);
778 ptr = (uchar *) ENTRY_VAL (obj, NPF_KICK_T);
779 if (ptr && *ptr && (StrnCaseCmp (ptr, "KOT-", 4) == 0)) {
780 int i;
782 ptr += 4;
783 for (i = 0; i < 8; i++) {
784 if (ptr[i] == '\0' || !isxdigit (ptr[i]))
785 break;
787 if (i == 8) {
788 pdb_set_kickoff_time (pw_buf,
789 (time_t) strtol (ptr, NULL, 16),
790 True);
794 pdb_set_pass_last_set_time (pw_buf, (time_t) 0);
795 ptr = (uchar *) ENTRY_VAL (obj, NPF_PWDLSET_T);
796 if (ptr && *ptr && (StrnCaseCmp (ptr, "LCT-", 4) == 0)) {
797 int i;
799 ptr += 4;
800 for (i = 0; i < 8; i++) {
801 if (ptr[i] == '\0' || !isxdigit (ptr[i]))
802 break;
804 if (i == 8) {
805 pdb_set_pass_last_set_time (pw_buf,
806 (time_t) strtol (ptr,
807 NULL,
808 16));
812 pdb_set_pass_can_change_time (pw_buf, (time_t) 0, True);
813 ptr = (uchar *) ENTRY_VAL (obj, NPF_PWDCCHG_T);
814 if (ptr && *ptr && (StrnCaseCmp (ptr, "CCT-", 4) == 0)) {
815 int i;
817 ptr += 4;
818 for (i = 0; i < 8; i++) {
819 if (ptr[i] == '\0' || !isxdigit (ptr[i]))
820 break;
822 if (i == 8) {
823 pdb_set_pass_can_change_time (pw_buf,
824 (time_t) strtol (ptr,
825 NULL,
826 16),
827 True);
831 pdb_set_pass_must_change_time (pw_buf, get_time_t_max (), True); /* Password never expires. */
832 ptr = (uchar *) ENTRY_VAL (obj, NPF_PWDMCHG_T);
833 if (ptr && *ptr && (StrnCaseCmp (ptr, "MCT-", 4) == 0)) {
834 int i;
836 ptr += 4;
837 for (i = 0; i < 8; i++) {
838 if (ptr[i] == '\0' || !isxdigit (ptr[i]))
839 break;
841 if (i == 8) {
842 pdb_set_pass_must_change_time (pw_buf,
843 (time_t) strtol (ptr,
844 NULL,
845 16),
846 True);
850 /* string values */
851 pdb_set_username (pw_buf, ENTRY_VAL (obj, NPF_NAME));
852 pdb_set_domain (pw_buf, lp_workgroup ());
853 /* pdb_set_nt_username() -- cant set it here... */
855 get_single_attribute (obj, NPF_FULL_NAME, full_name,
856 sizeof (pstring));
857 #if 0
858 unix_to_dos (full_name, True);
859 #endif
860 pdb_set_fullname (pw_buf, full_name);
862 pdb_set_acct_ctrl (pw_buf, pdb_decode_acct_ctrl (ENTRY_VAL (obj,
863 NPF_ACB)));
865 get_single_attribute (obj, NPF_ACCT_DESC, acct_desc,
866 sizeof (pstring));
867 #if 0
868 unix_to_dos (acct_desc, True);
869 #endif
870 pdb_set_acct_desc (pw_buf, acct_desc);
872 pdb_set_workstations (pw_buf, ENTRY_VAL (obj, NPF_WORKSTATIONS));
873 pdb_set_munged_dial (pw_buf, NULL);
875 pdb_set_uid (pw_buf, atoi (ENTRY_VAL (obj, NPF_UID)));
876 pdb_set_gid (pw_buf, atoi (ENTRY_VAL (obj, NPF_SMB_GRPID)));
877 pdb_set_user_sid_from_rid (pw_buf,
878 atoi (ENTRY_VAL (obj, NPF_USER_RID)));
879 pdb_set_group_sid_from_rid (pw_buf,
880 atoi (ENTRY_VAL (obj, NPF_GROUP_RID)));
882 /* values, must exist for user */
883 if (!(pdb_get_acct_ctrl (pw_buf) & ACB_WSTRUST)) {
885 get_single_attribute (obj, NPF_HOME_DIR, home_dir,
886 sizeof (pstring));
887 if (!(home_dir && *home_dir)) {
888 pstrcpy (home_dir, lp_logon_home ());
889 pdb_set_homedir (pw_buf, home_dir, False);
890 } else
891 pdb_set_homedir (pw_buf, home_dir, True);
893 get_single_attribute (obj, NPF_DIR_DRIVE, home_drive,
894 sizeof (pstring));
895 if (!(home_drive && *home_drive)) {
896 pstrcpy (home_drive, lp_logon_drive ());
897 pdb_set_dir_drive (pw_buf, home_drive, False);
898 } else
899 pdb_set_dir_drive (pw_buf, home_drive, True);
901 get_single_attribute (obj, NPF_LOGON_SCRIPT, logon_script,
902 sizeof (pstring));
903 if (!(logon_script && *logon_script)) {
904 pstrcpy (logon_script, lp_logon_script ());
905 } else
906 pdb_set_logon_script (pw_buf, logon_script, True);
908 get_single_attribute (obj, NPF_PROFILE_PATH, profile_path,
909 sizeof (pstring));
910 if (!(profile_path && *profile_path)) {
911 pstrcpy (profile_path, lp_logon_path ());
912 pdb_set_profile_path (pw_buf, profile_path, False);
913 } else
914 pdb_set_profile_path (pw_buf, profile_path, True);
916 } else {
917 /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */
918 pdb_set_group_sid_from_rid (pw_buf, DOMAIN_GROUP_RID_USERS);
921 /* Check the lanman password column. */
922 ptr = (char *) ENTRY_VAL (obj, NPF_LMPWD);
923 if (!pdb_set_lanman_passwd (pw_buf, NULL))
924 return False;
926 if (!strncasecmp (ptr, "NO PASSWORD", 11)) {
927 pdb_set_acct_ctrl (pw_buf,
928 pdb_get_acct_ctrl (pw_buf) | ACB_PWNOTREQ);
929 } else {
930 if (strlen (ptr) != 32 || !pdb_gethexpwd (ptr, smbpwd)) {
931 DEBUG (0, ("malformed LM pwd entry: %s.\n",
932 pdb_get_username (pw_buf)));
933 return False;
935 if (!pdb_set_lanman_passwd (pw_buf, smbpwd))
936 return False;
939 /* Check the NT password column. */
940 ptr = ENTRY_VAL (obj, NPF_NTPWD);
941 if (!pdb_set_nt_passwd (pw_buf, NULL))
942 return False;
944 if (!(pdb_get_acct_ctrl (pw_buf) & ACB_PWNOTREQ) &&
945 strncasecmp (ptr, "NO PASSWORD", 11)) {
946 if (strlen (ptr) != 32 || !pdb_gethexpwd (ptr, smbntpwd)) {
947 DEBUG (0, ("malformed NT pwd entry:\
948 uid = %d.\n", pdb_get_uid (pw_buf)));
949 return False;
951 if (!pdb_set_nt_passwd (pw_buf, smbntpwd))
952 return False;
955 pdb_set_unknown_3 (pw_buf, 0xffffff); /* don't know */
956 pdb_set_logon_divs (pw_buf, 168); /* hours per week */
958 if ((hours_len = ENTRY_LEN (obj, NPF_HOURS)) == 21) {
959 memcpy (hours, ENTRY_VAL (obj, NPF_HOURS), hours_len);
960 } else {
961 hours_len = 21; /* 21 times 8 bits = 168 */
962 /* available at all hours */
963 memset (hours, 0xff, hours_len);
965 pdb_set_hours_len (pw_buf, hours_len);
966 pdb_set_hours (pw_buf, hours);
968 pdb_set_unknown_5 (pw_buf, 0x00020000); /* don't know */
969 pdb_set_unknown_6 (pw_buf, 0x000004ec); /* don't know */
971 return True;
974 /************************************************************************
975 makes a struct sam_passwd from a NIS+ result.
976 ************************************************************************/
977 static BOOL make_sam_from_nisresult (SAM_ACCOUNT * pw_buf,
978 const nis_result * result)
980 if (pw_buf == NULL || result == NULL)
981 return False;
983 if (result->status != NIS_SUCCESS && result->status != NIS_NOTFOUND) {
984 DEBUG (0, ("NIS+ lookup failure: %s\n",
985 nis_sperrno (result->status)));
986 return False;
989 /* User not found. */
990 if (NIS_RES_NUMOBJ (result) <= 0) {
991 DEBUG (10, ("user not found in NIS+\n"));
992 return False;
995 if (NIS_RES_NUMOBJ (result) > 1) {
996 DEBUG (10,
997 ("WARNING: Multiple entries for user in NIS+ table!\n"));
1000 /* Grab the first hit. */
1001 return make_sam_from_nisp_object (pw_buf,
1002 &NIS_RES_OBJECT (result)[0]);
1005 /*************************************************************************
1006 sets a NIS+ attribute
1007 *************************************************************************/
1008 static void set_single_attribute (nis_object * new_obj, int col,
1009 const char *val, int len, int flags)
1011 if (new_obj == NULL)
1012 return;
1014 ENTRY_VAL (new_obj, col) = val;
1015 ENTRY_LEN (new_obj, col) = len + 1;
1017 if (flags != 0) {
1018 new_obj->EN_data.en_cols.en_cols_val[col].ec_flags = flags;
1022 /***************************************************************
1023 copy or modify nis object. this object is used to add or update
1024 nisplus table entry.
1025 ****************************************************************/
1026 static BOOL init_nisp_from_sam (nis_object * obj, const SAM_ACCOUNT * sampass,
1027 nis_object * old)
1030 * Fill nis_object for entry add or update.
1031 * if we are updateing, we have to find out differences and set
1032 * EN_MODIFIED flag. also set need_to_modify to trigger
1033 * nis_modify_entry() call in pdb_update_sam_account().
1035 * TODO:
1036 * get data from SAM
1037 * if (modify) get data from nis_object, compare and store if
1038 * different + set EN_MODIFIED and need_to_modify
1039 * else
1040 * store
1042 BOOL need_to_modify = False;
1043 const char *name = pdb_get_username (sampass); /* from SAM */
1045 /* these must be static or allocate and free entry columns! */
1046 static fstring uid; /* from SAM */
1047 static fstring user_rid; /* from SAM */
1048 static fstring gid; /* from SAM */
1049 static fstring group_rid; /* from SAM */
1050 char *acb; /* from SAM */
1051 static fstring smb_passwd; /* from SAM */
1052 static fstring smb_nt_passwd; /* from SAM */
1053 static fstring logon_t; /* from SAM */
1054 static fstring logoff_t; /* from SAM */
1055 static fstring kickoff_t; /* from SAM */
1056 static fstring pwdlset_t; /* from SAM */
1057 static fstring pwdlchg_t; /* from SAM */
1058 static fstring pwdmchg_t; /* from SAM */
1059 static fstring full_name; /* from SAM */
1060 static fstring acct_desc; /* from SAM */
1061 static char empty[1]; /* just an empty string */
1063 slprintf (uid, sizeof (uid) - 1, "%u", pdb_get_uid (sampass));
1064 slprintf (user_rid, sizeof (user_rid) - 1, "%u",
1065 pdb_get_user_rid (sampass) ? pdb_get_user_rid (sampass) :
1066 fallback_pdb_uid_to_user_rid (pdb_get_uid (sampass)));
1067 slprintf (gid, sizeof (gid) - 1, "%u", pdb_get_gid (sampass));
1070 uint32 rid;
1071 GROUP_MAP map;
1073 rid = pdb_get_group_rid (sampass);
1075 if (rid == 0) {
1076 if (get_group_map_from_gid
1077 (pdb_get_gid (sampass), &map,
1078 MAPPING_WITHOUT_PRIV)) {
1079 if (!sid_peek_check_rid
1080 (get_global_sam_sid (), &map.sid, &rid))
1081 return False;
1082 } else
1083 rid = pdb_gid_to_group_rid (pdb_get_gid
1084 (sampass));
1087 slprintf (group_rid, sizeof (group_rid) - 1, "%u", rid);
1090 acb = pdb_encode_acct_ctrl (pdb_get_acct_ctrl (sampass),
1091 NEW_PW_FORMAT_SPACE_PADDED_LEN);
1092 pdb_sethexpwd (smb_passwd, pdb_get_lanman_passwd (sampass),
1093 pdb_get_acct_ctrl (sampass));
1094 pdb_sethexpwd (smb_nt_passwd, pdb_get_nt_passwd (sampass),
1095 pdb_get_acct_ctrl (sampass));
1096 slprintf (logon_t, 13, "LNT-%08X",
1097 (uint32) pdb_get_logon_time (sampass));
1098 slprintf (logoff_t, 13, "LOT-%08X",
1099 (uint32) pdb_get_logoff_time (sampass));
1100 slprintf (kickoff_t, 13, "KOT-%08X",
1101 (uint32) pdb_get_kickoff_time (sampass));
1102 slprintf (pwdlset_t, 13, "LCT-%08X",
1103 (uint32) pdb_get_pass_last_set_time (sampass));
1104 slprintf (pwdlchg_t, 13, "CCT-%08X",
1105 (uint32) pdb_get_pass_can_change_time (sampass));
1106 slprintf (pwdmchg_t, 13, "MCT-%08X",
1107 (uint32) pdb_get_pass_must_change_time (sampass));
1108 safe_strcpy (full_name, pdb_get_fullname (sampass),
1109 sizeof (full_name) - 1);
1110 safe_strcpy (acct_desc, pdb_get_acct_desc (sampass),
1111 sizeof (acct_desc) - 1);
1113 #if 0
1115 /* Not sure what to do with these guys. -tpot */
1117 dos_to_unix (full_name, True);
1118 dos_to_unix (acct_desc, True);
1120 #endif
1122 if (old) {
1123 /* name */
1124 if (strcmp (ENTRY_VAL (old, NPF_NAME), name)) {
1125 need_to_modify = True;
1126 set_single_attribute (obj, NPF_NAME, name,
1127 strlen (name), EN_MODIFIED);
1131 /* uid */
1132 if (pdb_get_uid (sampass) != -1) {
1133 if (!ENTRY_VAL (old, NPF_UID)
1134 || strcmp (ENTRY_VAL (old, NPF_UID), uid)) {
1135 need_to_modify = True;
1136 set_single_attribute (obj, NPF_UID, uid,
1137 strlen (uid),
1138 EN_MODIFIED);
1142 /* user_rid */
1143 if (pdb_get_user_rid (sampass)) {
1144 if (!ENTRY_VAL (old, NPF_USER_RID) ||
1145 strcmp (ENTRY_VAL (old, NPF_USER_RID),
1146 user_rid)) {
1147 need_to_modify = True;
1148 set_single_attribute (obj, NPF_USER_RID,
1149 user_rid,
1150 strlen (user_rid),
1151 EN_MODIFIED);
1155 /* smb_grpid */
1156 if (pdb_get_gid (sampass) != -1) {
1157 if (!ENTRY_VAL (old, NPF_SMB_GRPID) ||
1158 strcmp (ENTRY_VAL (old, NPF_SMB_GRPID), gid)) {
1159 need_to_modify = True;
1160 set_single_attribute (obj, NPF_SMB_GRPID, gid,
1161 strlen (gid),
1162 EN_MODIFIED);
1166 /* group_rid */
1167 if (pdb_get_group_rid (sampass)) {
1168 if (!ENTRY_VAL (old, NPF_GROUP_RID) ||
1169 strcmp (ENTRY_VAL (old, NPF_GROUP_RID),
1170 group_rid)) {
1171 need_to_modify = True;
1172 set_single_attribute (obj, NPF_GROUP_RID,
1173 group_rid,
1174 strlen (group_rid),
1175 EN_MODIFIED);
1179 /* acb */
1180 if (!ENTRY_VAL (old, NPF_ACB) ||
1181 strcmp (ENTRY_VAL (old, NPF_ACB), acb)) {
1182 need_to_modify = True;
1183 set_single_attribute (obj, NPF_ACB, acb, strlen (acb),
1184 EN_MODIFIED);
1187 /* lmpwd */
1188 if (!ENTRY_VAL (old, NPF_LMPWD) ||
1189 strcmp (ENTRY_VAL (old, NPF_LMPWD), smb_passwd)) {
1190 need_to_modify = True;
1191 set_single_attribute (obj, NPF_LMPWD, smb_passwd,
1192 strlen (smb_passwd),
1193 EN_CRYPT | EN_MODIFIED);
1196 /* ntpwd */
1197 if (!ENTRY_VAL (old, NPF_NTPWD) ||
1198 strcmp (ENTRY_VAL (old, NPF_NTPWD), smb_nt_passwd)) {
1199 need_to_modify = True;
1200 set_single_attribute (obj, NPF_NTPWD, smb_nt_passwd,
1201 strlen (smb_nt_passwd),
1202 EN_CRYPT | EN_MODIFIED);
1205 /* logon_t */
1206 if (pdb_get_logon_time (sampass) &&
1207 (!ENTRY_VAL (old, NPF_LOGON_T) ||
1208 strcmp (ENTRY_VAL (old, NPF_LOGON_T), logon_t))) {
1209 need_to_modify = True;
1210 set_single_attribute (obj, NPF_LOGON_T, logon_t,
1211 strlen (logon_t), EN_MODIFIED);
1214 /* logoff_t */
1215 if (pdb_get_logoff_time (sampass) &&
1216 (!ENTRY_VAL (old, NPF_LOGOFF_T) ||
1217 strcmp (ENTRY_VAL (old, NPF_LOGOFF_T), logoff_t))) {
1218 need_to_modify = True;
1219 set_single_attribute (obj, NPF_LOGOFF_T, logoff_t,
1220 strlen (logoff_t), EN_MODIFIED);
1223 /* kick_t */
1224 if (pdb_get_kickoff_time (sampass) &&
1225 (!ENTRY_VAL (old, NPF_KICK_T) ||
1226 strcmp (ENTRY_VAL (old, NPF_KICK_T), kickoff_t))) {
1227 need_to_modify = True;
1228 set_single_attribute (obj, NPF_KICK_T, kickoff_t,
1229 strlen (kickoff_t),
1230 EN_MODIFIED);
1233 /* pwdlset_t */
1234 if (pdb_get_pass_last_set_time (sampass) &&
1235 (!ENTRY_VAL (old, NPF_PWDLSET_T) ||
1236 strcmp (ENTRY_VAL (old, NPF_PWDLSET_T), pwdlset_t))) {
1237 need_to_modify = True;
1238 set_single_attribute (obj, NPF_PWDLSET_T, pwdlset_t,
1239 strlen (pwdlset_t),
1240 EN_MODIFIED);
1243 /* pwdlchg_t */
1244 if (pdb_get_pass_can_change_time (sampass) &&
1245 (!ENTRY_VAL (old, NPF_PWDCCHG_T) ||
1246 strcmp (ENTRY_VAL (old, NPF_PWDCCHG_T), pwdlchg_t))) {
1247 need_to_modify = True;
1248 set_single_attribute (obj, NPF_PWDCCHG_T, pwdlchg_t,
1249 strlen (pwdlchg_t),
1250 EN_MODIFIED);
1253 /* pwdmchg_t */
1254 if (pdb_get_pass_must_change_time (sampass) &&
1255 (!ENTRY_VAL (old, NPF_PWDMCHG_T) ||
1256 strcmp (ENTRY_VAL (old, NPF_PWDMCHG_T), pwdmchg_t))) {
1257 need_to_modify = True;
1258 set_single_attribute (obj, NPF_PWDMCHG_T, pwdmchg_t,
1259 strlen (pwdmchg_t),
1260 EN_MODIFIED);
1263 /* full_name */
1264 /* must support set, unset and change */
1265 if ((pdb_get_fullname (sampass) &&
1266 !ENTRY_VAL (old, NPF_FULL_NAME)) ||
1267 (ENTRY_VAL (old, NPF_FULL_NAME) &&
1268 !pdb_get_fullname (sampass)) ||
1269 (ENTRY_VAL (old, NPF_FULL_NAME) &&
1270 pdb_get_fullname (sampass) &&
1271 strcmp (ENTRY_VAL (old, NPF_FULL_NAME), full_name))) {
1272 need_to_modify = True;
1273 set_single_attribute (obj, NPF_FULL_NAME, full_name,
1274 strlen (full_name),
1275 EN_MODIFIED);
1278 /* home_dir */
1279 /* must support set, unset and change */
1280 if ((pdb_get_homedir (sampass) &&
1281 !ENTRY_VAL (old, NPF_HOME_DIR)) ||
1282 (ENTRY_VAL (old, NPF_HOME_DIR) &&
1283 !pdb_get_homedir (sampass)) ||
1284 (ENTRY_VAL (old, NPF_HOME_DIR) &&
1285 pdb_get_homedir (sampass) &&
1286 strcmp (ENTRY_VAL (old, NPF_HOME_DIR),
1287 pdb_get_homedir (sampass)))) {
1288 need_to_modify = True;
1289 set_single_attribute (obj, NPF_HOME_DIR,
1290 pdb_get_homedir (sampass),
1291 strlen (pdb_get_homedir
1292 (sampass)),
1293 EN_MODIFIED);
1296 /* dir_drive */
1297 /* must support set, unset and change */
1298 if ((pdb_get_dir_drive (sampass) &&
1299 !ENTRY_VAL (old, NPF_DIR_DRIVE)) ||
1300 (ENTRY_VAL (old, NPF_DIR_DRIVE) &&
1301 !pdb_get_dir_drive (sampass)) ||
1302 (ENTRY_VAL (old, NPF_DIR_DRIVE) &&
1303 pdb_get_dir_drive (sampass) &&
1304 strcmp (ENTRY_VAL (old, NPF_DIR_DRIVE),
1305 pdb_get_dir_drive (sampass)))) {
1306 need_to_modify = True;
1307 set_single_attribute (obj, NPF_DIR_DRIVE,
1308 pdb_get_dir_drive (sampass),
1309 strlen (pdb_get_dir_drive
1310 (sampass)),
1311 EN_MODIFIED);
1314 /* logon_script */
1315 /* must support set, unset and change */
1316 if (((pdb_get_logon_script (sampass) &&
1317 !ENTRY_VAL (old, NPF_LOGON_SCRIPT)) ||
1318 ((ENTRY_VAL (old, NPF_LOGON_SCRIPT) &&
1319 (!pdb_get_logon_script (sampass)))) ||
1320 ((ENTRY_VAL (old, NPF_LOGON_SCRIPT) &&
1321 pdb_get_logon_script (sampass) &&
1322 strcmp (ENTRY_VAL (old, NPF_LOGON_SCRIPT),
1323 pdb_get_logon_script (sampass)))))) {
1324 need_to_modify = True;
1325 set_single_attribute (obj, NPF_LOGON_SCRIPT,
1326 pdb_get_logon_script (sampass),
1327 strlen (pdb_get_logon_script
1328 (sampass)),
1329 EN_MODIFIED);
1332 /* profile_path */
1333 /* must support set, unset and change */
1334 if ((pdb_get_profile_path (sampass) &&
1335 !ENTRY_VAL (old, NPF_PROFILE_PATH)) ||
1336 (ENTRY_VAL (old, NPF_PROFILE_PATH) &&
1337 !pdb_get_profile_path (sampass)) ||
1338 (ENTRY_VAL (old, NPF_PROFILE_PATH) &&
1339 pdb_get_profile_path (sampass) &&
1340 strcmp (ENTRY_VAL (old, NPF_PROFILE_PATH),
1341 pdb_get_profile_path (sampass)))) {
1342 need_to_modify = True;
1343 set_single_attribute (obj, NPF_PROFILE_PATH,
1344 pdb_get_profile_path (sampass),
1345 strlen (pdb_get_profile_path
1346 (sampass)),
1347 EN_MODIFIED);
1350 /* acct_desc */
1351 /* must support set, unset and change */
1352 if ((pdb_get_acct_desc (sampass) &&
1353 !ENTRY_VAL (old, NPF_ACCT_DESC)) ||
1354 (ENTRY_VAL (old, NPF_ACCT_DESC) &&
1355 !pdb_get_acct_desc (sampass)) ||
1356 (ENTRY_VAL (old, NPF_ACCT_DESC) &&
1357 pdb_get_acct_desc (sampass) &&
1358 strcmp (ENTRY_VAL (old, NPF_ACCT_DESC), acct_desc))) {
1359 need_to_modify = True;
1360 set_single_attribute (obj, NPF_ACCT_DESC, acct_desc,
1361 strlen (acct_desc),
1362 EN_MODIFIED);
1365 /* workstations */
1366 /* must support set, unset and change */
1367 if ((pdb_get_workstations (sampass) &&
1368 !ENTRY_VAL (old, NPF_WORKSTATIONS)) ||
1369 (ENTRY_VAL (old, NPF_WORKSTATIONS) &&
1370 !pdb_get_workstations (sampass)) ||
1371 (ENTRY_VAL (old, NPF_WORKSTATIONS) &&
1372 (pdb_get_workstations (sampass)) &&
1373 strcmp (ENTRY_VAL (old, NPF_WORKSTATIONS),
1374 pdb_get_workstations (sampass)))) {
1375 need_to_modify = True;
1376 set_single_attribute (obj, NPF_WORKSTATIONS,
1377 pdb_get_workstations (sampass),
1378 strlen (pdb_get_workstations
1379 (sampass)),
1380 EN_MODIFIED);
1383 /* hours */
1384 if ((pdb_get_hours_len (sampass) !=
1385 ENTRY_LEN (old, NPF_HOURS))
1386 || memcmp (pdb_get_hours (sampass),
1387 ENTRY_VAL (old, NPF_HOURS), ENTRY_LEN (old,
1388 NPF_HOURS)))
1390 need_to_modify = True;
1391 /* set_single_attribute will add 1 for len ... */
1392 set_single_attribute (obj, NPF_HOURS,
1393 pdb_get_hours (sampass),
1394 pdb_get_hours_len (sampass) - 1,
1395 EN_MODIFIED);
1397 } else {
1398 const char *homedir, *dirdrive, *logon_script, *profile_path,
1399 *workstations;
1401 *empty = '\0'; /* empty string */
1403 set_single_attribute (obj, NPF_NAME, name, strlen (name), 0);
1404 set_single_attribute (obj, NPF_UID, uid, strlen (uid), 0);
1405 set_single_attribute (obj, NPF_USER_RID, user_rid,
1406 strlen (user_rid), 0);
1407 set_single_attribute (obj, NPF_SMB_GRPID, gid, strlen (gid),
1409 set_single_attribute (obj, NPF_GROUP_RID, group_rid,
1410 strlen (group_rid), 0);
1411 set_single_attribute (obj, NPF_ACB, acb, strlen (acb), 0);
1412 set_single_attribute (obj, NPF_LMPWD, smb_passwd,
1413 strlen (smb_passwd), EN_CRYPT);
1414 set_single_attribute (obj, NPF_NTPWD, smb_nt_passwd,
1415 strlen (smb_nt_passwd), EN_CRYPT);
1416 set_single_attribute (obj, NPF_LOGON_T, logon_t,
1417 strlen (logon_t), 0);
1418 set_single_attribute (obj, NPF_LOGOFF_T, logoff_t,
1419 strlen (logoff_t), 0);
1420 set_single_attribute (obj, NPF_KICK_T, kickoff_t,
1421 strlen (kickoff_t), 0);
1422 set_single_attribute (obj, NPF_PWDLSET_T, pwdlset_t,
1423 strlen (pwdlset_t), 0);
1424 set_single_attribute (obj, NPF_PWDCCHG_T, pwdlchg_t,
1425 strlen (pwdlchg_t), 0);
1426 set_single_attribute (obj, NPF_PWDMCHG_T, pwdmchg_t,
1427 strlen (pwdmchg_t), 0);
1428 set_single_attribute (obj, NPF_FULL_NAME,
1429 full_name, strlen (full_name), 0);
1431 if (!(homedir = pdb_get_homedir (sampass)))
1432 homedir = empty;
1434 set_single_attribute (obj, NPF_HOME_DIR,
1435 homedir, strlen (homedir), 0);
1437 if (!(dirdrive = pdb_get_dir_drive (sampass)))
1438 dirdrive = empty;
1440 set_single_attribute (obj, NPF_DIR_DRIVE,
1441 dirdrive, strlen (dirdrive), 0);
1443 if (!(logon_script = pdb_get_logon_script (sampass)))
1444 logon_script = empty;
1446 set_single_attribute (obj, NPF_LOGON_SCRIPT,
1447 logon_script, strlen (logon_script), 0);
1449 if (!(profile_path = pdb_get_profile_path (sampass)))
1450 profile_path = empty;
1452 set_single_attribute (obj, NPF_PROFILE_PATH,
1453 profile_path, strlen (profile_path), 0);
1455 set_single_attribute (obj, NPF_ACCT_DESC,
1456 acct_desc, strlen (acct_desc), 0);
1458 if (!(workstations = pdb_get_workstations (sampass)))
1459 workstations = empty;
1461 set_single_attribute (obj, NPF_WORKSTATIONS,
1462 workstations, strlen (workstations), 0);
1464 /* set_single_attribute will add 1 for len ... */
1465 set_single_attribute (obj, NPF_HOURS,
1466 pdb_get_hours (sampass),
1467 pdb_get_hours_len (sampass) - 1, 0);
1470 return need_to_modify;
1473 /***************************************************************
1474 calls nis_list, returns results.
1475 ****************************************************************/
1476 static nis_result *nisp_get_nis_list (const char *nisname, unsigned int flags)
1478 nis_result *result;
1479 int i;
1481 if (!flags)
1482 flags = FOLLOW_LINKS | FOLLOW_PATH | EXPAND_NAME |
1483 HARD_LOOKUP;
1485 for (i = 0; i < 2; i++) {
1486 alarm (60); /* hopefully ok for long searches */
1487 result = nis_list (nisname, flags, NULL, NULL);
1489 alarm (0);
1490 CatchSignal (SIGALRM, SIGNAL_CAST SIG_DFL);
1492 if (!(flags & MASTER_ONLY) && NIS_RES_NUMOBJ (result) <= 0) {
1493 /* nis replicas are not in sync perhaps?
1494 * this can happen, if account was just added.
1496 DEBUG (10, ("will try master only\n"));
1497 nis_freeresult (result);
1498 flags |= MASTER_ONLY;
1499 } else
1500 break;
1502 return result;
1505 NTSTATUS pdb_init_nisplussam (PDB_CONTEXT * pdb_context,
1506 PDB_METHODS ** pdb_method, const char *location)
1508 NTSTATUS nt_status;
1509 struct nisplus_private_info *private = malloc (sizeof (struct nisplus_private_info));
1511 ZERO_STRUCT(private);
1512 p->location = talloc_strdup(pdb_context->mem_ctx, location);
1514 if (!NT_STATUS_IS_OK
1515 (nt_status =
1516 make_pdb_methods (pdb_context->mem_ctx, pdb_method))) {
1517 return nt_status;
1520 (*pdb_method)->name = "nisplussam";
1522 /* Functions your pdb module doesn't provide should be set
1523 * to NULL */
1525 (*pdb_method)->setsampwent = nisplussam_setsampwent;
1526 (*pdb_method)->endsampwent = nisplussam_endsampwent;
1527 (*pdb_method)->getsampwent = nisplussam_getsampwent;
1528 (*pdb_method)->getsampwnam = nisplussam_getsampwnam;
1529 (*pdb_method)->getsampwsid = nisplussam_getsampwsid;
1530 (*pdb_method)->add_sam_account = nisplussam_add_sam_account;
1531 (*pdb_method)->update_sam_account = nisplussam_update_sam_account;
1532 (*pdb_method)->delete_sam_account = nisplussam_delete_sam_account;
1533 (*pdb_method)->private_data = private;
1535 return NT_STATUS_OK;
1538 #else
1539 NTSTATUS pdb_init_nisplussam (PDB_CONTEXT * c, PDB_METHODS ** m,
1540 const char *l)
1542 DEBUG (0, ("nisplus sam not compiled in!\n"));
1543 return NT_STATUS_UNSUCCESSFUL;
1545 #endif /* WITH_NISPLUS_SAM */