source: trunk/third/moira/incremental/ldap/winad.c @ 24319

Revision 24319, 252.9 KB checked in by broder, 15 years ago (diff)
New Moira snapshot from SVN.
  • Property svn:executable set to *
Line 
1/* $HeadURL: svn+ssh://svn.mit.edu/moira/trunk/moira/incremental/ldap/winad.c $ $Id: winad.c 3969 2010-01-31 05:07:55Z zacheiss $ */
2/* ldap.incr arguments example
3 *
4 * arguments when moira creates the account - ignored by ldap.incr since the
5 * account is unusable. users 0 11 #45198 45198 /bin/cmd cmd Last First Middle
6 * 0 950000001 2000 121049
7 *
8 * login, unix_uid, shell, winconsoleshell, last,
9 * first, middle, status, mitid, type, moiraid
10 *
11 * arguments for creating or updating a user account
12 * users 11 11 username 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF
13 * 121058  PathToHomeDir PathToProfileDir username 45206 /bin/cmd cmd Last
14 * First Middle 1 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
15 * users 11 11 #45206 45206 /bin/cmd cmd Last First Middle 0 950000001 STAFF
16 * 121058  PathToHomeDir PathToProfileDir newuser 45206 /bin/cmd cmd Last
17 * First Middle 2 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
18 *
19 * login, unix_uid, shell, winconsoleshell, last, first, middle, status,
20 * mitid, type, moiraid
21 *
22 * arguments for deactivating/deleting a user account
23 * users 11 11 username 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF
24 * 121058  PathToHomeDir PathToProfileDir username 45206 /bin/cmd cmd Last
25 * First Middle 3 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
26 * users 11 11 username 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF
27 * 121058  PathToHomeDir PathToProfileDir username 45206 /bin/cmd cmd Last
28 * First Middle 3 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
29 *
30 * login, unix_uid, shell, winconsoleshell, last, first, middle, status,
31 * mitid, type, moiraid
32 *
33 * arguments for reactivating a user account
34 * users 11 11 username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF
35 * 121058 username 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF
36 * 121058
37 * users 11 11 username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF
38 * 121058 username 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF 12105
39 *
40 * login, unix_uid, shell, winconsoleshell, last, first, middle, status,
41 * mitid, type, moiraid
42 *
43 * arguments for changing user name
44 * users 11 11 oldusername 45206 /bin/cmd cmd Last First Middle 1 950000001
45 * STAFF 121058 PathToHomeDir PathToProfileDir newusername 45206 /bin/cmd cmd
46 * Last First Middle 1 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
47 *
48 * login, unix_uid, shell, winconsoleshell, last, first, middle, status,
49 * mitid, type, moiraid
50 *
51 * arguments for expunging a user
52 * users 11 0 username 45198 /bin/cmd cmd Last First Middle 0 950000001 2000
53 * 121049
54 *
55 * login, unix_uid, shell, winconsoleshell, last, first, middle, status,
56 * mitid, type, moiraid
57 *
58 * arguments for creating a "special" group/list
59 * list 0 11 listname 1 1 0 0 0 -1 NONE 0 description 92616
60 *
61 * listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type,
62 * acl_id, description, moiraid
63 *
64 * arguments for creating a "mail" group/list
65 * list 0 11 listname 1 1 0 1 0 -1 NONE 0 description 92616
66 *
67 * listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type,
68 * acl_id, description, moiraid
69 *
70 * arguments for creating a "group" group/list
71 * list 0 11 listname 1 1 0 0 1 -1 NONE 0 description 92616
72 *
73 * listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type,
74 * acl_id, description, moiraid
75 *
76 * arguments for creating a "group/mail" group/list
77 * list 0 11 listname 1 1 0 1 1 -1 NONE 0 description 92616
78 *
79 * listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type,
80 * acl_id, description, moiraid
81 *
82 * arguments to add a USER member to group/list
83 * imembers 0 12 listname USER userName 1 1 0 0 0 -1 1 92616 121047
84 *
85 * list_name, user_type, name, active, publicflg, hidden, maillist, grouplist,
86 * gid, userStatus, moiraListId, moiraUserId
87 *
88 * arguments to add a STRING or KERBEROS member to group/list
89 * imembers 0 10 listname STRING stringName 1 1 0 0 0 -1 92616
90 * imembers 0 10 listlistnameName KERBEROS kerberosName 1 1 0 0 0 -1 92616
91 *
92 * list_name, user_type, name, active, publicflg, hidden, maillist, grouplist,
93 * gid, moiraListId
94 *
95 * NOTE: group members of type LIST are ignored.
96 *
97 * arguments to remove a USER member to group/list
98 * imembers 12 0 listname USER userName 1 1 0 0 0 -1 1 92616 121047
99 *
100 * list_name, user_type, name, active, publicflg, hidden, maillist, grouplist,
101 * gid, userStatus, moiraListId, moiraUserId
102 *
103 * arguments to remove a STRING or KERBEROS member to group/list
104 * imembers 10 0 listname STRING stringName 1 1 0 0 0 -1 92616
105 * imembers 10 0 listname KERBEROS kerberosName 1 1 0 0 0 -1 92616
106 *
107 * list_name, user_type, name, active, publicflg, hidden, maillist, grouplist,
108 * gid, moiraListId
109 *
110 * NOTE: group members of type LIST are ignored.
111 *
112 * arguments for renaming a group/list
113 * list 11 11 oldlistname 1 1 0 0 0 -1 NONE 0 description 92616 newlistname 1
114 * 1 0 0 0 -1 description 0 92616
115 *
116 * name, active, publicflg, hidden, maillist, grouplist, gid, acl_type,
117 * acl_id, description, moiraListId
118 *
119 * arguments for deleting a group/list
120 * list 11 0 listname 1 1 0 0 0 -1 NONE 0 description 92616
121 *
122 * name, active, publicflg, hidden, maillist, grouplist, gid, acl_type,
123 * acl_id, description, moiraListId
124 *
125 * arguments for adding a file system
126 * filesys 0 12 username AFS ATHENA.MIT.EDU
127 * /afs/athena.mit.edu/user/n/e/username /mit/username w descripton username
128 * wheel 1 HOMEDIR 101727
129 *
130 * arguments for deleting a file system
131 * filesys 12 0 username AFS ATHENA.MIT.EDU
132 * /afs/athena.mit.edu/user/n/e/username /mit/username w descripton username
133 * wheel 1 HOMEDIR 101727
134 *
135 * arguments when moira creates a container (OU).
136 * containers 0 8 machines/test/bottom description location contact USER
137 * 105316 2222 [none]
138 *
139 * arguments when moira deletes a container (OU).
140 * containers 8 0 machines/test/bottom description location contact USER
141 * 105316 2222 groupname
142 *
143 * arguments when moira modifies a container information (OU).
144 * containers 8 8 machines/test/bottom description location contact USER
145 * 105316 2222 groupname machines/test/bottom description1 location contact
146 * USER 105316 2222 groupname
147 *
148 * arguments when moira adds a machine from an OU
149 * table name, beforec, afterc, machine_name, container_name, mach_id, cnt_id
150 * mcntmap 0 5 DAVIDT.MIT.EDU dttest/dttest1 76767 46 groupname
151 *
152 * arguments when moira removes a machine from an OU
153 * table name, beforec, afterc, machine_name, container_name, mach_id, cnt_id
154 * mcntmap 0 5 DAVIDT.MIT.EDU dttest/dttest1 76767 46 groupname
155 *
156*/
157
158#include <mit-copyright.h>
159
160#ifdef _WIN32
161#include <winsock2.h>
162#include <windows.h>
163#include <stdlib.h>
164#include <malloc.h>
165#include <lmaccess.h>
166#endif
167
168#include <hesiod.h>
169#include <string.h>
170#include <ldap.h>
171#include <stdio.h>
172#include <moira.h>
173#include <moira_site.h>
174#include <mrclient.h>
175#include <sasl/sasl.h>
176#include <krb5.h>
177
178#ifdef _WIN32
179#ifndef ECONNABORTED
180#define ECONNABORTED WSAECONNABORTED
181#endif
182#ifndef ECONNREFUSED
183#define ECONNREFUSED WSAECONNREFUSED
184#endif
185#ifndef EHOSTUNREACH
186#define EHOSTUNREACH WSAEHOSTUNREACH
187#endif
188#define krb5_xfree free
189#define F_OK 0
190#define sleep(A) Sleep(A * 1000);
191#endif /* _WIN32 */
192
193#ifndef _WIN32
194#include <sys/types.h>
195#include <netinet/in.h>
196#include <arpa/nameser.h>
197#include <resolv.h>
198#include <sys/utsname.h>
199#include <unistd.h>
200
201#define CFG_PATH "/moira/ldap/"
202#define WINADCFG "ldap.cfg"
203#define strnicmp(A,B,C) strncasecmp(A,B,C)
204#define UCHAR unsigned char
205
206#define UF_SCRIPT               0x0001
207#define UF_ACCOUNTDISABLE       0x0002
208#define UF_HOMEDIR_REQUIRED     0x0008
209#define UF_LOCKOUT              0x0010
210#define UF_PASSWD_NOTREQD       0x0020
211#define UF_PASSWD_CANT_CHANGE   0x0040
212#define UF_DONT_EXPIRE_PASSWD   0x10000
213
214#define UF_TEMP_DUPLICATE_ACCOUNT       0x0100
215#define UF_NORMAL_ACCOUNT               0x0200
216#define UF_INTERDOMAIN_TRUST_ACCOUNT    0x0800
217#define UF_WORKSTATION_TRUST_ACCOUNT    0x1000
218#define UF_SERVER_TRUST_ACCOUNT         0x2000
219
220#define OWNER_SECURITY_INFORMATION       (0x00000001L)
221#define GROUP_SECURITY_INFORMATION       (0x00000002L)
222#define DACL_SECURITY_INFORMATION        (0x00000004L)
223#define SACL_SECURITY_INFORMATION        (0x00000008L)
224
225#ifndef BYTE
226#define BYTE unsigned char
227#endif
228typedef unsigned int DWORD;
229typedef unsigned long ULONG;
230
231typedef struct _GUID
232{
233  unsigned long Data1;
234  unsigned short Data2;
235  unsigned short Data3;
236  unsigned char Data4[8];
237} GUID;
238
239typedef struct _SID_IDENTIFIER_AUTHORITY {
240  BYTE Value[6];
241} SID_IDENTIFIER_AUTHORITY, *PSID_IDENTIFIER_AUTHORITY;
242
243typedef struct _SID {
244  BYTE  Revision;
245  BYTE  SubAuthorityCount;
246  SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
247  DWORD SubAuthority[512];
248} SID;
249#endif/*!WIN32*/
250
251#ifndef WINADCFG
252#define WINADCFG "ldap.cfg"
253#endif
254
255#ifndef CFG_PATH
256#define CFG_PATH ""
257#endif
258
259#define AFS "/afs/"
260#define WINAFS "\\\\afs\\all\\"
261
262#define ADS_GROUP_TYPE_GLOBAL_GROUP         0x00000002
263#define ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP   0x00000004
264#define ADS_GROUP_TYPE_LOCAL_GROUP          0x00000004
265#define ADS_GROUP_TYPE_UNIVERSAL_GROUP      0x00000008
266#define ADS_GROUP_TYPE_SECURITY_ENABLED     0x80000000
267
268#define QUERY_VERSION   -1
269#define PRIMARY_REALM   "ATHENA.MIT.EDU"
270#define PRIMARY_DOMAIN  "win.mit.edu"
271#define PRODUCTION_PRINCIPAL "sms"
272#define TEST_PRINCIPAL       "smstest"
273
274#define SUBSTITUTE  1
275#define REPLACE     2
276
277#define USERS         0
278#define GROUPS        1
279
280#define MEMBER_ADD          1
281#define MEMBER_REMOVE       2
282#define MEMBER_CHANGE_NAME  3
283#define MEMBER_ACTIVATE     4
284#define MEMBER_DEACTIVATE   5
285#define MEMBER_CREATE       6
286
287#define MOIRA_ALL       0x0
288#define MOIRA_USERS     0x1
289#define MOIRA_KERBEROS  0x2
290#define MOIRA_STRINGS   0x4
291#define MOIRA_LISTS     0x8
292#define MOIRA_MACHINE   0x16
293
294#define CHECK_GROUPS    1
295#define CLEANUP_GROUPS  2
296
297#define AD_NO_GROUPS_FOUND        -1
298#define AD_WRONG_GROUP_DN_FOUND   -2
299#define AD_MULTIPLE_GROUPS_FOUND  -3
300#define AD_INVALID_NAME           -4
301#define AD_LDAP_FAILURE           -5
302#define AD_INVALID_FILESYS        -6
303#define AD_NO_ATTRIBUTE_FOUND     -7
304#define AD_NO_OU_FOUND            -8
305#define AD_NO_USER_FOUND          -9
306
307/* container arguments */
308#define CONTAINER_NAME       0
309#define CONTAINER_DESC       1
310#define CONTAINER_LOCATION   2
311#define CONTAINER_CONTACT    3
312#define CONTAINER_TYPE       4
313#define CONTAINER_ID         5
314#define CONTAINER_ROWID      6
315#define CONTAINER_GROUP_NAME 7
316
317/*mcntmap arguments*/
318#define OU_MACHINE_NAME        0
319#define OU_CONTAINER_NAME      1
320#define OU_MACHINE_ID          2
321#define OU_CONTAINER_ID        3
322#define OU_CONTAINER_GROUP     4
323
324typedef struct lk_entry {
325  int     op;
326  int     length;
327  int     ber_value;
328  char    *dn;
329  char    *attribute;
330  char    *value;
331  char    *member;
332  char    *type;
333  char    *list;
334  struct  lk_entry *next;
335} LK_ENTRY;
336
337#define STOP_FILE "/moira/ldap/noldap"
338#define file_exists(file) (access((file), F_OK) == 0)
339
340#define N_SD_BER_BYTES   5
341#define LDAP_BERVAL struct berval
342#define MAX_SERVER_NAMES 32
343
344#define HIDDEN_GROUP                "HiddenGroup.g"
345#define HIDDEN_GROUP_WITH_ADMIN     "HiddenGroupWithAdmin.g"
346#define NOT_HIDDEN_GROUP            "NotHiddenGroup.g"
347#define NOT_HIDDEN_GROUP_WITH_ADMIN "NotHiddenGroupWithAdmin.g"
348
349#define ADDRESS_LIST_PREFIX "CN=MIT Directory,CN=All Address Lists,\
350CN=Address Lists Container,CN=Massachusetts Institute of Technology,\
351CN=Microsoft Exchange,CN=Services,CN=Configuration,"
352
353#define GLOBAL_ADDRESS_LIST_PREFIX "CN=Default Global Address List,\
354CN=All Global Address Lists,CN=Address Lists Container,\
355CN=Massachusetts Institute of Technology,CN=Microsoft Exchange,CN=Services,\
356CN=Configuration,"
357
358#define EMAIL_ADDRESS_LIST_PREFIX "CN=Email Users,CN=All Users,\
359CN=All Address Lists,CN=Address Lists Container,\
360CN=Massachusetts Institute of Technology,CN=Microsoft Exchange,\
361CN=Services,CN=Configuration,"
362
363#define ALL_ADDRESS_LIST_PREFIX "CN=All Users,CN=All Address Lists,\
364CN=Address Lists Container,CN=Massachusetts Institute of Technology,\
365CN=Microsoft Exchange,CN=Services,CN=Configuration,"
366
367#define X500_PREFIX "X500:/o=Massachusetts Institute of Technology/\
368ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients"
369
370#define ADD_ATTR(t, v, o)               \
371  mods[n] = malloc(sizeof(LDAPMod));    \
372  mods[n]->mod_op = o;                  \
373  mods[n]->mod_type = t;                \
374  mods[n++]->mod_values = v
375
376#define DEL_ATTR(t, o)                  \
377  DelMods[i] = malloc(sizeof(LDAPMod)); \
378  DelMods[i]->mod_op = o;               \
379  DelMods[i]->mod_type = t;             \
380  DelMods[i++]->mod_values = NULL
381
382#define DOMAIN_SUFFIX   "MIT.EDU"
383#define DOMAIN  "DOMAIN:"
384#define PRINCIPALNAME  "PRINCIPAL:"
385#define SERVER  "SERVER:"
386#define MSSFU   "SFU:"
387#define SFUTYPE "30"
388#define GROUP_SUFFIX "GROUP_SUFFIX:"
389#define GROUP_TYPE   "GROUP_TYPE:"
390#define SET_GROUP_ACE    "SET_GROUP_ACE:"
391#define SET_PASSWORD "SET_PASSWORD:"
392#define EXCHANGE "EXCHANGE:"
393#define REALM "REALM:"
394#define ACTIVE_DIRECTORY "ACTIVE_DIRECTORY:"
395#define PORT "PORT:"
396#define PROCESS_MACHINE_CONTAINER "PROCESS_MACHINE_CONTAINER:"
397#define GROUP_POPULATE_MEMBERS "GROUP_POPULATE_MEMBERS:"
398#define MAX_MEMBERS "MAX_MEMBERS:"
399#define MAX_DOMAINS 10
400char DomainNames[MAX_DOMAINS][128];
401
402LK_ENTRY *member_base = NULL;
403
404LDAP *ldap_handle = NULL;
405
406char   PrincipalName[128];
407static char tbl_buf[1024];
408char  kerberos_ou[] = "OU=kerberos,OU=moira";
409char  contact_ou[] = "OU=strings,OU=moira";
410char  user_ou[] = "OU=users,OU=moira";
411char  group_ou_distribution[1024];
412char  group_ou_root[1024];
413char  group_ou_security[1024];
414char  group_ou_neither[1024];
415char  group_ou_both[1024];
416char  orphans_machines_ou[] = "OU=Machines,OU=Orphans";
417char  orphans_other_ou[] = "OU=Other,OU=Orphans";
418char  security_template_ou[] = "OU=security_templates";
419char *whoami;
420char ldap_domain[256];
421char ldap_realm[256];
422char ldap_port[256];
423char *ServerList[MAX_SERVER_NAMES];
424char default_server[256];
425char connected_server[128];
426static char tbl_buf[1024];
427char group_suffix[256];
428char exchange_acl[256];
429int  mr_connections = 0;
430int  callback_rc;
431int  UseSFU30 = 0;
432int  UseGroupSuffix = 1;
433int  UseGroupUniversal = 0;
434int  SetGroupAce = 1;
435int  SetPassword = 1;
436int  Exchange = 0;
437int  ProcessMachineContainer = 1;
438int  ActiveDirectory = 1;
439int  UpdateDomainList;
440int  fsgCount;
441int  GroupPopulateDelete = 0;
442int  group_members = 0;
443int  max_group_members = 0;
444
445struct sockaddr_in  kdc_server;
446int                 kdc_socket;
447krb5_context        context;
448krb5_ccache         ccache;
449krb5_auth_context   auth_context = NULL;
450krb5_data           ap_req;
451krb5_creds          *credsp = NULL;
452krb5_creds          creds;
453
454extern int set_password(char *user, char *password, char *domain);
455
456int ad_get_group(LDAP *ldap_handle, char *dn_path, char *group_name,
457                 char *group_membership, char *MoiraId, char *attribute,
458                 LK_ENTRY **linklist_base, int *linklist_count,
459                 char *rFilter);
460void AfsToWinAfs(char* path, char* winPath);
461int ad_connect(LDAP **ldap_handle, char *ldap_domain, char *dn_path,
462               char *Win2kPassword, char *Win2kUser, char *default_server,
463               int connect_to_kdc, char **ServerList, char *ldap_realm,
464               char *ldap_port);
465void ad_kdc_disconnect(void);
466int ad_server_connect(char *connectedServer, char *domain);
467int attribute_update(LDAP *ldap_handle, char *distinguished_name,
468                     char *attribute_value, char *attribute, char *user_name);
469int BEREncodeSecurityBits(ULONG uBits, char *pBuffer);
470int checkADname(LDAP *ldap_handle, char *dn_path, char *Name);
471int check_winad(void);
472int check_user(LDAP *ldap_handle, char *dn_path, char *UserName,
473               char *MoiraId);
474/* containers */
475int container_adupdate(LDAP *ldap_handle, char *dn_path, char *dName,
476                       char *distinguishedName, int count, char **av);
477void container_check(LDAP *ldap_handle, char *dn_path, char *name);
478int container_create(LDAP *ldap_handle, char *dn_path, int count, char **av);
479int container_delete(LDAP *ldap_handle, char *dn_path, int count, char **av);
480int container_get_distinguishedName(LDAP *ldap_handle, char *dn_path,
481                                    char *distinguishedName, int count,
482                                    char **av);
483void container_get_dn(char *src, char *dest);
484void container_get_name(char *src, char *dest);
485int container_move_objects(LDAP *ldap_handle, char *dn_path, char *dName);
486int container_rename(LDAP *ldap_handle, char *dn_path, int beforec,
487                     char **before, int afterc, char **after);
488int container_update(LDAP *ldap_handle, char *dn_path, int beforec,
489                     char **before, int afterc, char **after);
490
491int GetAceInfo(int ac, char **av, void *ptr);
492int get_group_membership(char *group_membership, char *group_ou,
493                         int *security_flag, char **av);
494int get_machine_ou(LDAP *ldap_handle, char *dn_path, char *member,
495                   char *machine_ou, char *pPtr);
496int Moira_container_group_create(char **after);
497int Moira_container_group_delete(char **before);
498int Moira_groupname_create(char *GroupName, char *ContainerName,
499                           char *ContainerRowID);
500int Moira_container_group_update(char **before, char **after);
501int Moira_process_machine_container_group(char *MachineName, char* groupName,
502                                          int DeleteMachine);
503int Moira_addGroupToParent(char *origContainerName, char *GroupName);
504int Moira_getContainerGroup(int ac, char **av, void *ptr);
505int Moira_getGroupName(char *origContainerName, char *GroupName,
506                       int ParentFlag);
507int Moira_setContainerGroup(char *ContainerName, char *GroupName);
508int ProcessAce(LDAP *ldap_handle, char *dn_path, char *group_name, char *Type,
509               int UpdateGroup, int *ProcessGroup, char *maillist,
510               char *nfsgroup);
511int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId,
512                  char *group_name, char *group_ou, char *group_membership,
513                  int group_security_flag, int type, char *maillist,
514                  char *nfsgroup);
515int process_lists(int ac, char **av, void *ptr);
516int ProcessGroupSecurity(LDAP *ldap_handle, char *dn_path,
517                         char *TargetGroupName, int HiddenGroup,
518                         char *AceType, char *AceName);
519int ProcessMachineName(int ac, char **av, void *ptr);
520int ReadConfigFile(char *DomainName);
521int ReadDomainList();
522void StringTrim(char *StringToTrim);
523char *escape_string(char *s);
524int save_query_info(int argc, char **argv, void *hint);
525int save_fsgroup_info(int argc, char **argv, void *hint);
526int user_create(int ac, char **av, void *ptr);
527int user_change_status(LDAP *ldap_handle, char *dn_path,
528                       char *user_name, char *MoiraId, int operation);
529int user_delete(LDAP *ldap_handle, char *dn_path,
530                char *u_name, char *MoiraId);
531int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name,
532                char *user_name);
533int user_update(LDAP *ldap_handle, char *dn_path, char *user_name,
534                char *uid, char *MitId, char *MoiraId, int State,
535                char *WinHomeDir, char *WinProfileDir, char *first,
536                char *middle, char *last, char *shell, char *class);
537void change_to_lower_case(char *ptr);
538int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou);
539int contact_remove_email(LDAP *ld, char *bind_path,
540                         LK_ENTRY **linklist_entry, int linklist_current);
541int group_create(int ac, char **av, void *ptr);
542int group_delete(LDAP *ldap_handle, char *dn_path,
543                 char *group_name, char *group_membership, char *MoiraId);
544int group_rename(LDAP *ldap_handle, char *dn_path,
545                 char *before_group_name, char *before_group_membership,
546                 char *before_group_ou, int before_security_flag,
547                 char *before_desc, char *after_group_name,
548                 char *after_group_membership, char *after_group_ou,
549                 int after_security_flag, char *after_desc,
550                 char *MoiraId, char *filter, char *maillist, char *nfsgroup);
551int machine_check(LDAP *ldap_handle, char *dn_path, char *machine_name);
552int machine_GetMoiraContainer(int ac, char **av, void *ptr);
553int machine_get_moira_container(LDAP *ldap_handle, char *dn_path,
554                                char *machine_name, char *container_name);
555int machine_move_to_ou(LDAP *ldap_handle, char *dn_path,
556                       char *MoiraMachineName, char *DestinationOu);
557int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId,
558                   char *group_name, char *group_ou, char *group_membership,
559                   int group_security_flag, int updateGroup, char *maillist,
560                   char *nfsgroup);
561int member_list_build(int ac, char **av, void *ptr);
562int member_add(LDAP *ldap_handle, char *dn_path, char *group_name,
563               char *group_ou, char *group_membership,
564               char *user_name, char *pUserOu, char *MoiraId);
565int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name,
566                  char *group_ou, char *group_membership, char *user_name,
567                  char *pUserOu, char *MoiraId);
568int contains_member(LDAP *ldap_handle, char *dn_path, char *group_name,
569                   char *UserOu, char *member);
570int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name,
571                   char *group_ou, char *group_membership,
572                   int group_security_flag, char *MoiraId, int synchronize);
573int SetHomeDirectory(LDAP *ldap_handle, char *user_name,
574                     char *DistinguishedName,
575                     char *WinHomeDir, char *WinProfileDir,
576                     char **homedir_v, char **winProfile_v,
577                     char **drives_v, char **apple_homedir_v, LDAPMod **mods,
578                     int OpType, int n);
579int sid_update(LDAP *ldap_handle, char *dn_path);
580void SwitchSFU(LDAPMod **mods, int *UseSFU30, int n);
581int check_string(char *s);
582int check_container_name(char* s);
583
584int mr_connect_cl(char *server, char *client, int version, int auth);
585void do_container(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
586                  char **before, int beforec, char **after, int afterc);
587void do_filesys(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
588                char **before, int beforec, char **after, int afterc);
589void do_list(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
590             char **before, int beforec, char **after, int afterc);
591void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
592             char **before, int beforec, char **after, int afterc);
593void do_member(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
594               char **before, int beforec, char **after, int afterc);
595void do_mcntmap(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
596                char **before, int beforec, char **after, int afterc);
597int linklist_create_entry(char *attribute, char *value,
598                          LK_ENTRY **linklist_entry);
599int linklist_build(LDAP *ldap_handle, char *dn_path, char *search_exp,
600                   char **attr_array, LK_ENTRY **linklist_base,
601                   int *linklist_count, unsigned long ScopeType);
602void linklist_free(LK_ENTRY *linklist_base);
603
604int retrieve_attributes(LDAP *ldap_handle, LDAPMessage *ldap_entry,
605                        char *distinguished_name, LK_ENTRY **linklist_current);
606int retrieve_entries(LDAP *ldap_handle, LDAPMessage *ldap_entry,
607                     LK_ENTRY **linklist_base, int *linklist_count);
608int retrieve_values(LDAP *ldap_handle, LDAPMessage *ldap_entry,
609                    char *Attribute, char *distinguished_name,
610                    LK_ENTRY **linklist_current);
611
612int construct_newvalues(LK_ENTRY *linklist_base, int modvalue_count,
613                        char *oldValue, char *newValue,
614                        char ***modvalues, int type);
615void free_values(char **modvalues);
616
617int convert_domain_to_dn(char *domain, char *dnp);
618void get_distinguished_name(LDAP *ldap_handle, LDAPMessage *ldap_entry,
619                            char *distinguished_name);
620int moira_disconnect(void);
621int moira_connect(void);
622void print_to_screen(const char *fmt, ...);
623int GetMachineName(char *MachineName);
624int tickets_get_k5();
625int destroy_cache(void);
626int dest_tkt(void);
627
628int find_homeMDB(LDAP *ldap_handle, char *dn_path, char **homeMDB,
629                 char **homeServerName);
630
631int main(int argc, char **argv)
632{
633  unsigned long   rc;
634  int             beforec;
635  int             afterc;
636  int             i;
637  int             j;
638  int             k;
639  int             OldUseSFU30;
640  char            *table;
641  char            **before;
642  char            **after;
643  char            dn_path[256];
644  char            *orig_argv[64];
645 
646  whoami = ((whoami = (char *)strrchr(argv[0], '/')) ? whoami+1 : argv[0]);
647 
648  if (argc < 4)
649    {
650      com_err(whoami, 0, "Unable to process %s", "argc < 4");
651      exit(1);
652    }
653 
654  if (argc < (4 + atoi(argv[2]) + atoi(argv[3])))
655    {
656      com_err(whoami, 0, "Unable to process %s",
657              "argc < (4 + beforec + afterc)");
658      exit(1);
659    }
660
661  if (!strcmp(argv[1], "filesys"))
662    exit(0);
663
664  for (i = 1; i < argc; i++)
665    {
666      strcat(tbl_buf, argv[i]);
667      strcat(tbl_buf, " ");
668    }
669
670  com_err(whoami, 0, "%s", tbl_buf);
671
672  if (check_winad())
673    {
674      com_err(whoami, 0, "%s failed", "check_winad()");
675      exit(1);
676    }
677
678  initialize_sms_error_table();
679  initialize_krb_error_table();
680
681  UpdateDomainList = 0;
682  memset(DomainNames, '\0', sizeof(DomainNames[0]) * MAX_DOMAINS);
683
684  if (ReadDomainList())
685    {
686      com_err(whoami, 0, "%s failed", "ReadDomainList()");
687      exit(1);
688    }
689
690  for (i = 0; i < argc; i++)
691     orig_argv[i] = NULL;
692
693  for (k = 0; k < MAX_DOMAINS; k++)
694    {
695      if (strlen(DomainNames[k]) == 0)
696        continue;
697      for (i = 0; i < argc; i++)
698        {
699          if (orig_argv[i] != NULL)
700            free(orig_argv[i]);
701          orig_argv[i] = strdup(argv[i]);
702        }
703
704      memset(PrincipalName, '\0', sizeof(PrincipalName));
705      memset(ldap_domain, '\0', sizeof(ldap_domain));
706      memset(ServerList, '\0', sizeof(ServerList[0]) * MAX_SERVER_NAMES);
707      memset(default_server, '\0', sizeof(default_server));
708      memset(dn_path, '\0', sizeof(dn_path));
709      memset(group_suffix, '\0', sizeof(group_suffix));
710      memset(exchange_acl, '\0', sizeof(exchange_acl));
711
712      UseSFU30 = 0;
713      UseGroupSuffix = 1;
714      UseGroupUniversal = 0;
715      SetGroupAce = 1;
716      SetPassword = 1;
717      Exchange = 0;
718      ProcessMachineContainer = 1;
719      ActiveDirectory = 1;
720
721      sprintf(group_suffix, "%s", "_group");
722      sprintf(exchange_acl, "%s", "exchange-acl");
723
724      beforec = atoi(orig_argv[2]);
725      afterc = atoi(orig_argv[3]);
726      table = orig_argv[1];
727      before = &orig_argv[4];
728      after = &orig_argv[4 + beforec];
729
730      if (afterc == 0)
731        after = NULL;
732
733      if (beforec == 0)
734        before = NULL;
735
736      if (ReadConfigFile(DomainNames[k]))
737        continue;
738
739      if(ActiveDirectory)
740        {
741          sprintf(group_ou_distribution, "OU=mail,OU=lists,OU=moira");
742          sprintf(group_ou_root, "OU=lists,OU=moira");
743          sprintf(group_ou_security, "OU=group,OU=lists,OU=moira");
744          sprintf(group_ou_neither, "OU=special,OU=lists,OU=moira");
745          sprintf(group_ou_both, "OU=mail,OU=group,OU=lists,OU=moira");
746        }
747      else
748        {
749          sprintf(group_ou_distribution, "OU=lists,OU=moira");
750          sprintf(group_ou_root, "OU=lists,OU=moira");
751          sprintf(group_ou_security, "OU=lists,OU=moira");
752          sprintf(group_ou_neither, "OU=lists,OU=moira");
753          sprintf(group_ou_both, "OU=lists,OU=moira");
754        }
755
756      OldUseSFU30 = UseSFU30;
757
758      for (i = 0; i < 5; i++)
759        {
760          ldap_handle = (LDAP *)NULL;
761          if (!(rc = ad_connect(&ldap_handle, ldap_domain, dn_path, "", "",
762                                default_server, SetPassword, ServerList,
763                                ldap_realm, ldap_port)))
764            {
765              com_err(whoami, 0, "connected to domain %s", DomainNames[k]);
766              break;
767            }
768        }
769
770      if ((rc) || (ldap_handle == NULL))
771        {
772          critical_alert(whoami, "incremental",
773                         "ldap.incr cannot connect to any server in "
774                         "domain %s", DomainNames[k]);
775          continue;
776        }
777
778      for (i = 0; i < (int)strlen(table); i++)
779        table[i] = tolower(table[i]);
780
781      if (!strcmp(table, "users"))
782        do_user(ldap_handle, dn_path, ldap_domain, before, beforec, after,
783                afterc);
784      else if (!strcmp(table, "list"))
785        do_list(ldap_handle, dn_path, ldap_domain, before, beforec, after,
786                afterc);
787      else if (!strcmp(table, "imembers"))
788        do_member(ldap_handle, dn_path, ldap_domain, before, beforec, after,
789                  afterc);
790      else if (!strcmp(table, "containers"))
791        do_container(ldap_handle, dn_path, ldap_domain, before, beforec, after,
792                     afterc);
793      else if (!strcmp(table, "mcntmap"))
794        do_mcntmap(ldap_handle, dn_path, ldap_domain, before, beforec, after,
795                   afterc);
796
797      if(SetPassword)
798        ad_kdc_disconnect();
799
800      for (i = 0; i < MAX_SERVER_NAMES; i++)
801        {
802          if (ServerList[i] != NULL)
803            {
804              free(ServerList[i]);
805              ServerList[i] = NULL;
806            }
807        }
808     
809      rc = ldap_unbind_s(ldap_handle);
810    }
811 
812  exit(0);
813}
814
815void do_mcntmap(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
816                char **before, int beforec, char **after, int afterc)
817{
818  char    MoiraContainerName[128];
819  char    ADContainerName[128];
820  char    MachineName[1024];
821  char    OriginalMachineName[1024];
822  long    rc;
823  int     DeleteMachine;
824  char    MoiraContainerGroup[64];
825
826  if (!ProcessMachineContainer)
827    {
828      com_err(whoami, 0, "Process machines and containers disabled, skipping");
829      return;
830    }
831 
832  DeleteMachine = 0;
833  memset(ADContainerName, '\0', sizeof(ADContainerName));
834  memset(MoiraContainerName, '\0', sizeof(MoiraContainerName));
835 
836  if ((beforec == 0) && (afterc == 0))
837    return;
838 
839  if (rc = moira_connect())
840    {
841      critical_alert(whoami, "Ldap incremental",
842                     "Error contacting Moira server : %s",
843                     error_message(rc));
844      return;
845    }
846 
847  if ((beforec != 0) && (afterc == 0)) /*remove a machine*/
848    {
849      strcpy(OriginalMachineName, before[OU_MACHINE_NAME]);
850      strcpy(MachineName, before[OU_MACHINE_NAME]);
851      strcpy(MoiraContainerGroup, before[OU_CONTAINER_GROUP]);
852      DeleteMachine = 1;
853      com_err(whoami, 0, "removing machine %s from %s",
854              OriginalMachineName, before[OU_CONTAINER_NAME]);
855    }
856  else if ((beforec == 0) && (afterc != 0)) /*add a machine*/
857    {
858      strcpy(OriginalMachineName, after[OU_MACHINE_NAME]);
859      strcpy(MachineName, after[OU_MACHINE_NAME]);
860      strcpy(MoiraContainerGroup, after[OU_CONTAINER_GROUP]);
861      com_err(whoami, 0, "adding machine %s to container %s",
862              OriginalMachineName, after[OU_CONTAINER_NAME]);
863    }
864  else
865    {
866      moira_disconnect();
867      return;
868    }
869 
870  rc = GetMachineName(MachineName);
871
872  if (strlen(MachineName) == 0)
873    {
874      moira_disconnect();
875      com_err(whoami, 0, "Unable to find alais for machine %s in Moira",
876              OriginalMachineName);
877      return;
878    }
879
880  Moira_process_machine_container_group(MachineName, MoiraContainerGroup,
881                                        DeleteMachine);
882
883  if (machine_check(ldap_handle, dn_path, MachineName))
884    {
885      com_err(whoami, 0, "Unable to find machine %s (alias %s) in directory.",
886              OriginalMachineName, MachineName);
887      moira_disconnect();
888      return;
889    }
890
891  memset(MoiraContainerName, '\0', sizeof(MoiraContainerName));
892  machine_get_moira_container(ldap_handle, dn_path, MachineName,
893                              MoiraContainerName);
894
895  if (strlen(MoiraContainerName) == 0)
896    {
897      com_err(whoami, 0, "Unable to fine machine %s (alias %s) container "
898              "in Moira - moving to orphans OU.",
899              OriginalMachineName, MachineName);
900      machine_move_to_ou(ldap_handle, dn_path, MachineName,
901                         orphans_machines_ou);
902      moira_disconnect();
903      return;
904    }
905
906  container_get_dn(MoiraContainerName, ADContainerName);
907
908  if (MoiraContainerName[strlen(MoiraContainerName) - 1] != '/')
909    strcat(MoiraContainerName, "/");
910
911  container_check(ldap_handle, dn_path, MoiraContainerName);
912  machine_move_to_ou(ldap_handle, dn_path, MachineName, ADContainerName);
913  moira_disconnect();
914  return;
915}
916
917void do_container(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
918                  char **before, int beforec, char **after, int afterc)
919{
920  long rc;
921
922  if (!ProcessMachineContainer)
923    {
924      com_err(whoami, 0, "Process machines and containers disabled, skipping");
925      return;
926    }
927
928  if ((beforec == 0) && (afterc == 0))
929    return;
930
931  if (rc = moira_connect())
932    {
933      critical_alert(whoami, "Ldap incremental", "Error contacting Moira server : %s",
934                     error_message(rc));
935      return;
936    }
937
938  if ((beforec != 0) && (afterc == 0)) /*delete a new container*/
939    {
940      com_err(whoami, 0, "deleting container %s", before[CONTAINER_NAME]);
941      container_delete(ldap_handle, dn_path, beforec, before);
942      Moira_container_group_delete(before);
943      moira_disconnect();
944      return;
945    }
946
947  if ((beforec == 0) && (afterc != 0)) /*create a container*/
948    {
949      com_err(whoami, 0, "creating container %s", after[CONTAINER_NAME]);
950      container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
951      container_create(ldap_handle, dn_path, afterc, after);
952      Moira_container_group_create(after);
953      moira_disconnect();
954      return;
955    }
956
957  if (strcasecmp(before[CONTAINER_NAME], after[CONTAINER_NAME]))
958    {
959      com_err(whoami, 0, "renaming container %s to %s",
960              before[CONTAINER_NAME], after[CONTAINER_NAME]);
961      container_rename(ldap_handle, dn_path, beforec, before, afterc, after);
962      Moira_container_group_update(before, after);
963      moira_disconnect();
964      return;
965    }
966
967  com_err(whoami, 0, "updating container %s information",
968          after[CONTAINER_NAME]);
969  container_update(ldap_handle, dn_path, beforec, before, afterc, after);
970  Moira_container_group_update(before, after);
971  moira_disconnect();
972  return;
973}
974
975#define L_LIST_DESC 9
976#define L_LIST_ID   10
977#define L_LIST_NFSGROUP 11
978
979void do_list(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
980             char **before, int beforec, char **after, int afterc)
981{
982  int   updateGroup;
983  int   ProcessGroup;
984  long  rc;
985  char  group_membership[6];
986  char  list_id[32];
987  int   security_flag;
988  char  filter[128];
989  char  group_ou[256];
990  char  before_list_id[32];
991  char  before_group_membership[1];
992  int   before_security_flag;
993  char  before_group_ou[256];
994  LK_ENTRY *ptr = NULL;
995
996  if (beforec == 0 && afterc == 0)
997    return;
998
999  memset(list_id, '\0', sizeof(list_id));
1000  memset(before_list_id, '\0', sizeof(before_list_id));
1001  memset(before_group_ou, '\0', sizeof(before_group_ou));
1002  memset(before_group_membership, '\0', sizeof(before_group_membership));
1003  memset(group_ou, '\0', sizeof(group_ou));
1004  memset(group_membership, '\0', sizeof(group_membership));
1005  updateGroup = 0;
1006
1007  if (beforec > L_GID)
1008    {
1009      if (beforec < L_LIST_ID)
1010        return;
1011      if (beforec > L_LIST_DESC)
1012        {
1013          strcpy(before_list_id, before[L_LIST_ID]);
1014        }
1015      before_security_flag = 0;
1016      get_group_membership(before_group_membership, before_group_ou,
1017                           &before_security_flag, before);
1018    }
1019
1020  if (afterc > L_GID)
1021    {
1022      if (afterc < L_LIST_ID)
1023        return;
1024      if (afterc > L_LIST_DESC)
1025        {
1026          strcpy(list_id, after[L_LIST_ID]);
1027        }
1028      security_flag = 0;
1029      get_group_membership(group_membership, group_ou, &security_flag, after);
1030    }
1031 
1032  if ((beforec == 0) && (afterc == 0)) /*this case should never happen*/
1033    return;
1034
1035  updateGroup = 0;
1036 
1037  if (beforec)
1038    {
1039      updateGroup = 1;
1040
1041      if ((rc = process_group(ldap_handle, dn_path, before_list_id,
1042                              before[L_NAME], before_group_ou,
1043                              before_group_membership,
1044                              before_security_flag, CHECK_GROUPS,
1045                              before[L_MAILLIST], before[L_LIST_NFSGROUP])))
1046        {
1047          if (rc == AD_NO_GROUPS_FOUND)
1048            updateGroup = 0;
1049          else
1050            {
1051              if ((rc == AD_WRONG_GROUP_DN_FOUND) ||
1052                  (rc == AD_MULTIPLE_GROUPS_FOUND))
1053                {
1054                  rc = process_group(ldap_handle, dn_path, before_list_id,
1055                                     before[L_NAME], before_group_ou,
1056                                     before_group_membership,
1057                                     before_security_flag, CLEANUP_GROUPS,
1058                                     before[L_MAILLIST],
1059                                     before[L_LIST_NFSGROUP]);
1060                }
1061              if ((rc != AD_NO_GROUPS_FOUND) && (rc != 0))
1062                {
1063                  com_err(whoami, 0, "Unable to process list %s",
1064                          before[L_NAME]);
1065                  return;
1066                }
1067              if (rc == AD_NO_GROUPS_FOUND)
1068                updateGroup = 0;
1069            }
1070        }
1071    }
1072
1073  if ((beforec != 0) && (afterc != 0))
1074    {
1075      if (((strcmp(after[L_NAME], before[L_NAME])) ||
1076           ((!strcmp(after[L_NAME], before[L_NAME])) &&
1077            (strcmp(before_group_ou, group_ou)))) &&
1078          (updateGroup == 1))
1079        {
1080          com_err(whoami, 0, "Changing list name from %s to %s",
1081                  before[L_NAME], after[L_NAME]);
1082
1083          if ((strlen(before_group_ou) == 0) ||
1084              (strlen(before_group_membership) == 0) ||
1085              (strlen(group_ou) == 0) || (strlen(group_membership) == 0))
1086            {
1087              com_err(whoami, 0, "%s", "Unable to find the group OU's");
1088              return;
1089            }
1090
1091          memset(filter, '\0', sizeof(filter));
1092
1093          if ((rc = group_rename(ldap_handle, dn_path,
1094                                 before[L_NAME], before_group_membership,
1095                                 before_group_ou, before_security_flag,
1096                                 before[L_LIST_DESC], after[L_NAME],
1097                                 group_membership, group_ou, security_flag,
1098                                 after[L_LIST_DESC],
1099                                 list_id, filter, after[L_MAILLIST],
1100                                 after[L_LIST_NFSGROUP])))
1101            {
1102              if (rc != AD_NO_GROUPS_FOUND)
1103                {
1104                  com_err(whoami, 0,
1105                          "Unable to change list name from %s to %s",
1106                          before[L_NAME], after[L_NAME]);
1107                  return;
1108                }
1109              updateGroup = 0;
1110            }
1111          beforec = 0;
1112        }
1113      else
1114        beforec = 0;
1115    }
1116 
1117  if (beforec)
1118    {
1119      if ((strlen(before_group_ou) == 0) ||
1120          (strlen(before_group_membership) == 0))
1121        {
1122          com_err(whoami, 0,
1123                  "Unable to find the group OU for group %s", before[L_NAME]);
1124          return;
1125        }
1126
1127      com_err(whoami, 0, "Deleting group %s", before[L_NAME]);
1128      rc = group_delete(ldap_handle, dn_path, before[L_NAME],
1129                        before_group_membership, before_list_id);
1130      return;
1131    }
1132
1133  if (afterc)
1134    {
1135      if (!updateGroup)
1136        {
1137          com_err(whoami, 0, "Creating group %s", after[L_NAME]);
1138
1139          if (rc = process_group(ldap_handle, dn_path, list_id, after[L_NAME],
1140                                  group_ou, group_membership,
1141                                  security_flag, CHECK_GROUPS,
1142                                 after[L_MAILLIST], after[L_LIST_NFSGROUP]))
1143            {
1144              if (rc != AD_NO_GROUPS_FOUND)
1145                {
1146                  if ((rc == AD_WRONG_GROUP_DN_FOUND) ||
1147                      (rc == AD_MULTIPLE_GROUPS_FOUND))
1148                    {
1149                      rc = process_group(ldap_handle, dn_path, list_id,
1150                                         after[L_NAME],
1151                                         group_ou, group_membership,
1152                                         security_flag, CLEANUP_GROUPS,
1153                                         after[L_MAILLIST],
1154                                         after[L_LIST_NFSGROUP]);
1155                    }
1156
1157                  if (rc)
1158                    {
1159                      com_err(whoami, 0,
1160                              "Unable to create list %s", after[L_NAME]);
1161                      return;
1162                    }
1163                }
1164            }
1165        }
1166      else
1167        com_err(whoami, 0, "Updating group %s information", after[L_NAME]);
1168
1169      if (rc = moira_connect())
1170        {
1171          critical_alert(whoami, "Ldap incremental",
1172                         "Error contacting Moira server : %s",
1173                         error_message(rc));
1174          return;
1175        }
1176
1177      ProcessGroup = 0;
1178
1179      if (ProcessAce(ldap_handle, dn_path, after[L_NAME], "LIST", 0,
1180                     &ProcessGroup, after[L_MAILLIST], after[L_LIST_NFSGROUP]))
1181        return;
1182
1183      if (ProcessGroup)
1184        {
1185          if (ProcessAce(ldap_handle, dn_path, after[L_NAME], "LIST", 1,
1186                         &ProcessGroup, after[L_MAILLIST],
1187                         after[L_LIST_NFSGROUP]))
1188            return;
1189        }
1190
1191      if (make_new_group(ldap_handle, dn_path, list_id, after[L_NAME],
1192                         group_ou, group_membership, security_flag,
1193                         updateGroup, after[L_MAILLIST],
1194                         after[L_LIST_NFSGROUP]))
1195        {
1196          moira_disconnect();
1197          return;
1198        }
1199   
1200      if (atoi(after[L_ACTIVE]))
1201        {
1202          populate_group(ldap_handle, dn_path, after[L_NAME], group_ou,
1203                         group_membership, security_flag, list_id, 1);
1204        }
1205
1206      moira_disconnect();
1207    }
1208  return;
1209}
1210
1211#define LM_EXTRA_ACTIVE   (LM_END)
1212#define LM_EXTRA_PUBLIC   (LM_END+1)
1213#define LM_EXTRA_HIDDEN   (LM_END+2)
1214#define LM_EXTRA_MAILLIST (LM_END+3)
1215#define LM_EXTRA_GROUP    (LM_END+4)
1216#define LM_EXTRA_GID      (LM_END+5)
1217#define LM_EXTRA_NFSGROUP (LM_END+6)
1218#define LMN_LIST_ID       (LM_END+7)
1219#define LM_LIST_ID        (LM_END+8)
1220#define LM_USER_ID        (LM_END+9)
1221#define LM_EXTRA_END      (LM_END+10)
1222
1223void do_member(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
1224               char **before, int beforec, char **after, int afterc)
1225{
1226  LK_ENTRY *group_base;
1227  int group_count;
1228  char  filter[128];
1229  char *attr_array[3];
1230  char  group_name[128];
1231  char  user_name[128];
1232  char  user_type[128];
1233  char  moira_list_id[32];
1234  char  moira_user_id[32];
1235  char  group_membership[1];
1236  char  group_ou[256];
1237  char  machine_ou[256];
1238  char  member[256];
1239  char  *args[16];
1240  char  **ptr;
1241  char  *av[7];
1242  char  *call_args[7];
1243  char  *pUserOu;
1244  char  *s;
1245  char  NewMachineName[1024];
1246  int   security_flag;
1247  int   rc;
1248  int   ProcessGroup;
1249  char  *save_argv[U_END];
1250
1251  pUserOu = NULL;
1252  ptr = NULL;
1253  memset(moira_list_id, '\0', sizeof(moira_list_id));
1254  memset(moira_user_id, '\0', sizeof(moira_user_id));
1255
1256  if (afterc)
1257    {
1258      if (afterc < LM_EXTRA_GID)
1259        return;
1260
1261      if (!atoi(after[LM_EXTRA_ACTIVE]))
1262        {
1263          com_err(whoami, 0,
1264                  "Unable to add %s to group %s : group not active",
1265                  after[2], after[0]);
1266          return;
1267        }
1268
1269      ptr = after;
1270
1271      if (!strcasecmp(ptr[LM_TYPE], "LIST"))
1272        return;
1273
1274      strcpy(user_name, after[LM_MEMBER]);
1275      strcpy(group_name, after[LM_LIST]);
1276      strcpy(user_type, after[LM_TYPE]);
1277
1278      if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1279        {
1280          if (afterc > LM_EXTRA_GROUP)
1281            {
1282              strcpy(moira_list_id, after[LMN_LIST_ID]);
1283              strcpy(moira_user_id, after[LM_LIST_ID]);
1284            }
1285        }
1286      else if (!strcasecmp(ptr[LM_TYPE], "USER"))
1287        {
1288          if (afterc > LMN_LIST_ID)
1289            {
1290              strcpy(moira_list_id, after[LM_LIST_ID]);
1291              strcpy(moira_user_id, after[LM_USER_ID]);
1292            }
1293        }
1294      else
1295        {
1296          if (afterc > LM_EXTRA_GID)
1297            strcpy(moira_list_id, after[LMN_LIST_ID]);
1298        }
1299    }
1300  else if (beforec)
1301    {
1302      if (beforec < LM_EXTRA_GID)
1303        return;
1304      if (!atoi(before[LM_EXTRA_ACTIVE]))
1305        {
1306          com_err(whoami, 0,
1307                  "Unable to remove %s from group %s : group not active",
1308                  before[2], before[0]);
1309          return;
1310        }
1311
1312      ptr = before;
1313
1314      if (!strcasecmp(ptr[LM_TYPE], "LIST"))
1315        return;
1316
1317      strcpy(user_name, before[LM_MEMBER]);
1318      strcpy(group_name, before[LM_LIST]);
1319      strcpy(user_type, before[LM_TYPE]);
1320
1321      if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1322        {
1323          if (beforec > LM_EXTRA_GROUP)
1324            {
1325              strcpy(moira_list_id, before[LMN_LIST_ID]);
1326              strcpy(moira_user_id, before[LM_LIST_ID]);
1327            }
1328        }
1329      else if (!strcasecmp(ptr[LM_TYPE], "USER"))
1330        {
1331          if (beforec > LMN_LIST_ID)
1332            {
1333              strcpy(moira_list_id, before[LM_LIST_ID]);
1334              strcpy(moira_user_id, before[LM_USER_ID]);
1335            }
1336        }
1337      else
1338        {
1339          if (beforec > LM_EXTRA_GID)
1340            strcpy(moira_list_id, before[LMN_LIST_ID]);
1341        }
1342    }
1343
1344  if (ptr == NULL)
1345    {
1346      com_err(whoami, 0,
1347              "Unable to process group : beforec = %d, afterc = %d",
1348              beforec, afterc);
1349      return;
1350    }
1351
1352  args[L_NAME] = ptr[LM_LIST];
1353  args[L_ACTIVE] = ptr[LM_EXTRA_ACTIVE];
1354  args[L_PUBLIC] = ptr[LM_EXTRA_PUBLIC];
1355  args[L_HIDDEN] = ptr[LM_EXTRA_HIDDEN];
1356  args[L_MAILLIST] = ptr[LM_EXTRA_MAILLIST];
1357  args[L_GROUP] = ptr[LM_EXTRA_GROUP];
1358  args[L_GID] = ptr[LM_EXTRA_GID];
1359
1360  security_flag = 0;
1361  memset(group_ou, '\0', sizeof(group_ou));
1362  get_group_membership(group_membership, group_ou, &security_flag, args);
1363
1364  if (strlen(group_ou) == 0)
1365    {
1366      com_err(whoami, 0, "Unable to find the group OU for group %s",
1367              group_name);
1368      return;
1369    }
1370
1371  if (rc = process_group(ldap_handle, dn_path, moira_list_id, group_name,
1372                         group_ou, group_membership, security_flag,
1373                         CHECK_GROUPS, args[L_MAILLIST],
1374                         args[L_LIST_NFSGROUP]))
1375    {
1376      if (rc != AD_NO_GROUPS_FOUND)
1377        {
1378          if (rc = process_group(ldap_handle, dn_path, moira_list_id,
1379                                 group_name, group_ou, group_membership,
1380                                 security_flag, CLEANUP_GROUPS,
1381                                 args[L_MAILLIST], args[L_LIST_NFSGROUP]))
1382            {
1383              if (rc != AD_NO_GROUPS_FOUND)
1384                {
1385                  if (afterc)
1386                    com_err(whoami, 0, "Unable to add %s to group %s - "
1387                            "unable to process group", user_name, group_name);
1388                  else
1389                    com_err(whoami, 0, "Unable to remove %s from group %s - "
1390                            "unable to process group", user_name, group_name);
1391                  return;
1392                }
1393            }
1394        }
1395    }
1396
1397  if (rc == AD_NO_GROUPS_FOUND)
1398    {
1399      if (rc = moira_connect())
1400        {
1401          critical_alert(whoami, "Ldap incremental",
1402                         "Error contacting Moira server : %s",
1403                         error_message(rc));
1404          return;
1405        }
1406     
1407      com_err(whoami, 0, "creating group %s", group_name);
1408      ProcessGroup = 0;
1409
1410      if (ProcessAce(ldap_handle, dn_path, ptr[LM_LIST], "LIST", 0,
1411                     &ProcessGroup, ptr[LM_EXTRA_MAILLIST],
1412                     ptr[LM_EXTRA_NFSGROUP]))
1413        return;
1414
1415      if (ProcessGroup)
1416        {
1417          if (ProcessAce(ldap_handle, dn_path, ptr[LM_LIST], "LIST", 1,
1418                         &ProcessGroup, ptr[LM_EXTRA_MAILLIST],
1419                         ptr[LM_EXTRA_NFSGROUP]))
1420            return;
1421        }
1422
1423      if (make_new_group(ldap_handle, dn_path, moira_list_id, ptr[LM_LIST],
1424                         group_ou, group_membership, security_flag, 0,
1425                         ptr[LM_EXTRA_MAILLIST], ptr[LM_EXTRA_NFSGROUP]))
1426        {
1427          moira_disconnect();
1428          return;
1429        }
1430   
1431      if (atoi(ptr[LM_EXTRA_ACTIVE]))
1432        {
1433          populate_group(ldap_handle, dn_path, ptr[LM_LIST], group_ou,
1434                         group_membership, security_flag, moira_list_id, 1);
1435        }
1436
1437      moira_disconnect();
1438    }
1439
1440  rc = 0;
1441
1442  if (beforec)
1443    {
1444      com_err(whoami, 0, "removing user %s from list %s", user_name,
1445              group_name);
1446      pUserOu = user_ou;
1447 
1448      if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1449        {
1450          if (!ProcessMachineContainer)
1451            {
1452              com_err(whoami, 0, "Process machines and containers disabled, "
1453                      "skipping");
1454              return;
1455            }
1456
1457          memset(machine_ou, '\0', sizeof(machine_ou));
1458          memset(NewMachineName, '\0', sizeof(NewMachineName));
1459          if (get_machine_ou(ldap_handle, dn_path, ptr[LM_MEMBER],
1460                             machine_ou, NewMachineName))
1461            return;
1462          if (ptr[LM_MEMBER] != NULL)     
1463            free(ptr[LM_MEMBER]);
1464          ptr[LM_MEMBER] = strdup(NewMachineName);
1465          pUserOu = machine_ou;
1466        }
1467
1468      if (!strcasecmp(ptr[LM_TYPE], "STRING"))
1469        {
1470          strcpy(member, ptr[LM_MEMBER]);
1471
1472          if (Exchange)
1473            {
1474              if((s = strchr(member, '@')) == (char *) NULL)
1475                return;
1476         
1477              if(!strncasecmp(&member[strlen(member) - 6], ".LOCAL", 6))
1478                return;
1479            }
1480
1481          if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER],
1482                             contact_ou))
1483                return;
1484
1485          pUserOu = contact_ou;
1486        }
1487      else if (!strcasecmp(ptr[LM_TYPE], "KERBEROS"))
1488        {
1489          if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER],
1490                             kerberos_ou))
1491            return;
1492
1493          pUserOu = kerberos_ou;
1494        }
1495
1496      if (rc = moira_connect()) {
1497        critical_alert(whoami, "Ldap incremental",
1498                       "Error contacting Moira server : %s",
1499                       error_message(rc));             
1500        return;
1501      }
1502     
1503      if (rc = populate_group(ldap_handle, dn_path, group_name,
1504                              group_ou, group_membership,
1505                              security_flag, moira_list_id, 0))
1506        com_err(whoami, 0, "Unable to remove %s from group %s", user_name,
1507                group_name);
1508     
1509      moira_disconnect();
1510
1511      if (rc = member_remove(ldap_handle, dn_path, group_name,
1512                             group_ou, group_membership,
1513                             escape_string(ptr[LM_MEMBER]),
1514                             pUserOu, moira_list_id))
1515        com_err(whoami, 0, "Unable to remove %s from group %s", user_name,
1516                group_name);
1517     
1518      return;
1519    }
1520 
1521  com_err(whoami, 0, "Adding %s to list %s", user_name, group_name);
1522  pUserOu = user_ou;
1523 
1524  if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1525    {
1526      memset(machine_ou, '\0', sizeof(machine_ou));
1527      memset(NewMachineName, '\0', sizeof(NewMachineName));
1528
1529      if (get_machine_ou(ldap_handle, dn_path, ptr[LM_MEMBER], machine_ou,
1530                         NewMachineName))
1531        return;
1532
1533      if (ptr[LM_MEMBER] != NULL)
1534        free(ptr[LM_MEMBER]);
1535
1536      ptr[LM_MEMBER] = strdup(NewMachineName);
1537      pUserOu = machine_ou;
1538    }
1539  else if (!strcasecmp(ptr[LM_TYPE], "STRING"))
1540    {
1541      strcpy(member, ptr[LM_MEMBER]);
1542
1543      if (Exchange)
1544        {
1545          if((s = strchr(member, '@')) == (char *) NULL)
1546            return;
1547         
1548          if(!strncasecmp(&member[strlen(member) - 6], ".LOCAL", 6))
1549            return;
1550        }
1551     
1552      if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER],
1553                         contact_ou))
1554        return;
1555
1556      pUserOu = contact_ou;
1557    }
1558  else if (!strcasecmp(ptr[LM_TYPE], "KERBEROS"))
1559    {
1560      if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER],
1561                         kerberos_ou))
1562        return;
1563
1564      pUserOu = kerberos_ou;
1565    }
1566  else if (!strcasecmp(ptr[LM_TYPE], "USER"))
1567    {
1568      if ((rc = check_user(ldap_handle, dn_path, ptr[LM_MEMBER],
1569                           moira_user_id)) == AD_NO_USER_FOUND)
1570        {
1571          if (rc = moira_connect())
1572            {
1573              critical_alert(whoami, "Ldap incremental",
1574                             "Error connection to Moira : %s",
1575                             error_message(rc));
1576              return;
1577            }
1578
1579          com_err(whoami, 0, "creating user %s", ptr[LM_MEMBER]);
1580          av[0] = ptr[LM_MEMBER];
1581          call_args[0] = (char *)ldap_handle;
1582          call_args[1] = dn_path;
1583          call_args[2] = moira_user_id;
1584          call_args[3] = NULL;
1585         
1586          callback_rc = 0;
1587
1588          if (Exchange)
1589            {
1590              group_count = 0;
1591              group_base = NULL;
1592         
1593              sprintf(filter, "(&(objectClass=group)(cn=%s))", ptr[LM_MEMBER]);
1594              attr_array[0] = "cn";
1595              attr_array[1] = NULL;
1596              if ((rc = linklist_build(ldap_handle, dn_path, filter,
1597                                       attr_array, &group_base, &group_count,
1598                                       LDAP_SCOPE_SUBTREE)) != 0)
1599                {
1600                  com_err(whoami, 0, "Unable to process user %s : %s",
1601                          ptr[LM_MEMBER], ldap_err2string(rc));
1602                  return;
1603                }
1604             
1605              if (group_count)
1606                {
1607                  com_err(whoami, 0, "Object already exists with name %s",
1608                          ptr[LM_MEMBER]);
1609                  return;
1610                }
1611         
1612              linklist_free(group_base);
1613              group_count = 0;
1614              group_base = NULL;
1615            }
1616
1617          if (rc = mr_query("get_user_account_by_login", 1, av,
1618                            save_query_info, save_argv))
1619            {
1620              moira_disconnect();
1621              com_err(whoami, 0, "Unable to create user %s : %s",
1622                      ptr[LM_MEMBER], error_message(rc));
1623              return;
1624            }
1625       
1626          if (rc = user_create(U_END, save_argv, call_args))
1627            {
1628              moira_disconnect();
1629              com_err(whoami, 0, "Unable to create user %s", ptr[LM_MEMBER]);
1630              return;
1631            }
1632
1633          if (callback_rc)
1634            {
1635              moira_disconnect();
1636              com_err(whoami, 0, "Unable to create user %s", ptr[LM_MEMBER]);
1637              return;
1638            }
1639        }
1640      else
1641        {
1642          if (rc != 0)
1643            return;
1644        }
1645      pUserOu = user_ou;
1646    }
1647
1648  if (rc = moira_connect()) {
1649    critical_alert(whoami, "Ldap incremental",
1650                   "Error contacting Moira server : %s",
1651                   error_message(rc));             
1652    return;
1653  }
1654
1655  if (rc = populate_group(ldap_handle, dn_path, group_name,
1656                          group_ou, group_membership, security_flag,
1657                          moira_list_id, 0))
1658    com_err(whoami, 0, "Unable to add %s to group %s", user_name,
1659            group_name);
1660 
1661  moira_disconnect();
1662
1663  if (rc = member_add(ldap_handle, dn_path, group_name,
1664                      group_ou, group_membership,
1665                      escape_string(ptr[LM_MEMBER]),
1666                      pUserOu, moira_list_id))
1667    com_err(whoami, 0, "Unable to add %s to group %s", user_name, group_name);
1668
1669  return;
1670}
1671
1672#define U_USER_ID    10
1673#define U_HOMEDIR    11
1674#define U_PROFILEDIR 12
1675#define U_POTYPE     13
1676
1677void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
1678             char **before, int beforec, char **after,
1679             int afterc)
1680{
1681  LK_ENTRY *group_base;
1682  int   group_count;
1683  char  filter[128];
1684  char  *attr_array[3];
1685  int   rc;
1686  char  *av[7];
1687  char  after_user_id[32];
1688  char  before_user_id[32];
1689  char  *call_args[7];
1690  char  *save_argv[U_END];
1691
1692  if ((beforec == 0) && (afterc == 0))
1693    return;
1694
1695  memset(after_user_id, '\0', sizeof(after_user_id));
1696  memset(before_user_id, '\0', sizeof(before_user_id));
1697
1698  if (beforec > U_USER_ID)
1699    strcpy(before_user_id, before[U_USER_ID]);
1700
1701  if (afterc > U_USER_ID)
1702    strcpy(after_user_id, after[U_USER_ID]);
1703
1704  if ((beforec == 0) && (afterc == 0)) /*this case should never happen */
1705    return;
1706
1707  if ((beforec == 0) && (afterc != 0))
1708    {
1709      /*this case only happens when the account*/
1710      /*account is first created but not usable*/
1711
1712      com_err(whoami, 0, "Unable to process user %s because the user account "
1713              "is not yet usable", after[U_NAME]);
1714      return;
1715    }
1716
1717  /*this case only happens when the account is expunged */
1718
1719  if ((beforec != 0) && (afterc == 0))
1720    {                                 
1721      if (atoi(before[U_STATE]) == 0)
1722        {
1723          com_err(whoami, 0, "expunging user %s from directory",
1724                  before[U_NAME]);
1725          user_delete(ldap_handle, dn_path, before[U_NAME], before_user_id);
1726        }
1727      else
1728        {
1729          com_err(whoami, 0, "Unable to process because user %s has been "
1730                  "previously expungeded", before[U_NAME]);
1731        }
1732      return;
1733    }
1734
1735  /*process anything that gets here*/
1736
1737  if ((rc = check_user(ldap_handle, dn_path, before[U_NAME],
1738                       before_user_id)) == AD_NO_USER_FOUND)
1739    {
1740      if (!check_string(after[U_NAME]))
1741        return;
1742
1743      if (rc = moira_connect())
1744        {
1745          critical_alert(whoami, "Ldap incremental",
1746                         "Error connection to Moira : %s",
1747                         error_message(rc));
1748          return;
1749        }
1750
1751      com_err(whoami, 0, "creating user %s", after[U_NAME]);
1752     
1753      av[0] = after[U_NAME];
1754      call_args[0] = (char *)ldap_handle;
1755      call_args[1] = dn_path;
1756      call_args[2] = after_user_id;
1757      call_args[3] = NULL;
1758      callback_rc = 0;
1759
1760      if (Exchange)
1761        {
1762          group_count = 0;
1763          group_base = NULL;
1764         
1765          sprintf(filter, "(&(objectClass=group)(cn=%s))", after[U_NAME]);
1766          attr_array[0] = "cn";
1767          attr_array[1] = NULL;
1768         
1769          if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
1770                                   &group_base, &group_count,
1771                                   LDAP_SCOPE_SUBTREE)) != 0)
1772            {
1773              com_err(whoami, 0, "Unable to process user %s : %s",
1774                      after[U_NAME], ldap_err2string(rc));
1775              return;
1776            }
1777         
1778          if (group_count >= 1)
1779            {
1780              com_err(whoami, 0, "Object already exists with name %s",
1781                      after[U_NAME]);
1782              return;
1783            }
1784     
1785          linklist_free(group_base);
1786          group_count = 0;
1787          group_base = NULL;
1788        }
1789
1790      if (rc = mr_query("get_user_account_by_login", 1, av,
1791                        save_query_info, save_argv))
1792        {
1793          moira_disconnect();
1794          com_err(whoami, 0, "Unable to create user %s : %s",
1795                  after[U_NAME], error_message(rc));
1796          return;
1797        }
1798
1799      if (rc = user_create(U_END, save_argv, call_args))
1800        {
1801          com_err(whoami, 0, "Unable to create user %s : %s",
1802                  after[U_NAME], error_message(rc));
1803          return;
1804        }
1805     
1806      if (callback_rc)
1807        {
1808          moira_disconnect();
1809          com_err(whoami, 0, "Unable to create user %s", after[U_NAME]);
1810          return;
1811        }
1812
1813      return;
1814    }
1815  else
1816    {
1817      if (rc != 0)
1818        return;
1819    }
1820
1821  if (strcmp(before[U_NAME], after[U_NAME]))
1822    {
1823      if ((check_string(before[U_NAME])) && (check_string(after[U_NAME])))
1824        {
1825          com_err(whoami, 0, "changing user %s to %s",
1826                  before[U_NAME], after[U_NAME]);
1827
1828          if ((rc = user_rename(ldap_handle, dn_path, before[U_NAME],
1829                                after[U_NAME])) != LDAP_SUCCESS)
1830            {
1831              return;
1832            }
1833        }
1834    }
1835
1836  com_err(whoami, 0, "updating user %s information", after[U_NAME]);
1837
1838  rc = user_update(ldap_handle, dn_path, after[U_NAME],
1839                   after[U_UID], after[U_MITID],
1840                   after_user_id, atoi(after[U_STATE]),
1841                   after[U_HOMEDIR], after[U_PROFILEDIR],
1842                   after[U_FIRST], after[U_MIDDLE], after[U_LAST],
1843                   after[U_SHELL], after[U_CLASS]);
1844
1845  return;
1846}
1847
1848int construct_newvalues(LK_ENTRY *linklist_base, int modvalue_count,
1849                        char *oldValue, char *newValue,
1850                        char ***modvalues, int type)
1851{
1852  LK_ENTRY    *linklist_ptr;
1853  int         i;
1854  char        *cPtr;
1855 
1856  if (((*modvalues) = calloc(1,
1857                             (modvalue_count + 1) * sizeof(char *))) == NULL)
1858    {
1859      return(1);
1860    }
1861
1862  for (i = 0; i < (modvalue_count + 1); i++)
1863    (*modvalues)[i] = NULL;
1864
1865  if (modvalue_count != 0)
1866    {
1867      linklist_ptr = linklist_base;
1868      for (i = 0; i < modvalue_count; i++)
1869        {
1870          if ((oldValue != NULL) && (newValue != NULL))
1871            {
1872              if ((cPtr = (char *)strstr(linklist_ptr->value, oldValue))
1873                  != (char *)NULL)
1874                {
1875                  if (type == REPLACE)
1876                    {
1877                      if (((*modvalues)[i] = calloc(1, strlen(newValue) + 1))
1878                          == NULL)
1879                        return(1);
1880                      memset((*modvalues)[i], '\0', strlen(newValue) + 1);
1881                      strcpy((*modvalues)[i], newValue);
1882                    }
1883                  else
1884                    {
1885                      if (((*modvalues)[i] = calloc(1,
1886                                        (int)(cPtr - linklist_ptr->value) +
1887                                               (linklist_ptr->length -
1888                                               strlen(oldValue)) +
1889                                               strlen(newValue) + 1)) == NULL)
1890                        return(1);
1891                      memset((*modvalues)[i], '\0',
1892                             (int)(cPtr - linklist_ptr->value) +
1893                             (linklist_ptr->length - strlen(oldValue)) +
1894                             strlen(newValue) + 1);
1895                      memcpy((*modvalues)[i], linklist_ptr->value,
1896                             (int)(cPtr - linklist_ptr->value));
1897                      strcat((*modvalues)[i], newValue);
1898                      strcat((*modvalues)[i],
1899                             &linklist_ptr->value[(int)(cPtr -
1900                                     linklist_ptr->value) + strlen(oldValue)]);
1901                    }
1902                }
1903              else
1904                {
1905                  (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
1906                  memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
1907                  memcpy((*modvalues)[i], linklist_ptr->value,
1908                         linklist_ptr->length);
1909                }
1910            }
1911        else
1912            {
1913              (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
1914              memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
1915              memcpy((*modvalues)[i], linklist_ptr->value,
1916                     linklist_ptr->length);
1917            }
1918          linklist_ptr = linklist_ptr->next;
1919        }
1920      (*modvalues)[i] = NULL;
1921    }
1922  return(0);
1923}
1924
1925
1926int linklist_build(LDAP *ldap_handle, char *dn_path, char *search_exp,
1927                   char **attr_array, LK_ENTRY **linklist_base,
1928                   int *linklist_count, unsigned long ScopeType)
1929{
1930  ULONG       rc;
1931  LDAPMessage *ldap_entry;
1932
1933  rc = 0;
1934  ldap_entry = NULL;
1935  (*linklist_base) = NULL;
1936  (*linklist_count) = 0;
1937
1938  if ((rc = ldap_search_s(ldap_handle, dn_path, ScopeType,
1939                          search_exp, attr_array, 0,
1940                          &ldap_entry)) != LDAP_SUCCESS)
1941      {
1942        if (rc != LDAP_SIZELIMIT_EXCEEDED)
1943          return(0);
1944      }
1945
1946  rc = retrieve_entries(ldap_handle, ldap_entry, linklist_base,
1947                        linklist_count);
1948
1949  ldap_msgfree(ldap_entry);
1950  return(rc);
1951}
1952
1953int retrieve_entries(LDAP *ldap_handle, LDAPMessage *ldap_entry,
1954                     LK_ENTRY **linklist_base, int *linklist_count)
1955{
1956  char        distinguished_name[1024];
1957  LK_ENTRY    *linklist_ptr;
1958  int         rc;
1959
1960  if ((ldap_entry = ldap_first_entry(ldap_handle, ldap_entry)) == NULL)
1961    return(0);
1962 
1963  memset(distinguished_name, '\0', sizeof(distinguished_name));
1964  get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
1965
1966  if ((rc = retrieve_attributes(ldap_handle, ldap_entry, distinguished_name,
1967                                linklist_base)) != 0)
1968    return(rc);
1969
1970  while ((ldap_entry = ldap_next_entry(ldap_handle, ldap_entry)) != NULL)
1971    {
1972      memset(distinguished_name, '\0', sizeof(distinguished_name));
1973      get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
1974     
1975      if ((rc = retrieve_attributes(ldap_handle, ldap_entry,
1976                                    distinguished_name, linklist_base)) != 0)
1977        return(rc);
1978    }
1979
1980  linklist_ptr = (*linklist_base);
1981  (*linklist_count) = 0;
1982
1983  while (linklist_ptr != NULL)
1984    {
1985      ++(*linklist_count);
1986      linklist_ptr = linklist_ptr->next;
1987    }
1988
1989  return(0);
1990}
1991
1992int retrieve_attributes(LDAP *ldap_handle, LDAPMessage *ldap_entry,
1993                        char *distinguished_name, LK_ENTRY **linklist_current)
1994{
1995  char        *Attribute;
1996  BerElement  *ptr;
1997
1998  ptr = NULL;
1999
2000  if ((Attribute = ldap_first_attribute(ldap_handle, ldap_entry,
2001                                        &ptr)) != NULL)
2002    {
2003      retrieve_values(ldap_handle, ldap_entry, Attribute, distinguished_name,
2004                      linklist_current);
2005      ldap_memfree(Attribute);
2006      while ((Attribute = ldap_next_attribute(ldap_handle, ldap_entry,
2007                                              ptr)) != NULL)
2008        {
2009          retrieve_values(ldap_handle, ldap_entry, Attribute,
2010                          distinguished_name, linklist_current);
2011          ldap_memfree(Attribute);
2012        }
2013    }
2014
2015  ldap_ber_free(ptr, 0);
2016
2017  return(0);
2018}
2019
2020int retrieve_values(LDAP *ldap_handle, LDAPMessage *ldap_entry,
2021                    char *Attribute, char *distinguished_name,
2022                    LK_ENTRY **linklist_current)
2023{
2024  char        **str_value;
2025  char        temp[256];
2026  void        **Ptr;
2027  int         use_bervalue;
2028  LK_ENTRY    *linklist_previous;
2029  LDAP_BERVAL **ber_value;
2030  DWORD       ber_length;
2031
2032#ifdef LDAP_DEBUG
2033  SID         *sid;
2034  GUID        *guid;
2035  int         i;
2036  int         intValue;
2037  DWORD       *subauth;
2038  SID_IDENTIFIER_AUTHORITY    *sid_auth;
2039  unsigned char   *subauth_count;
2040#endif /*LDAP_BEGUG*/
2041
2042  use_bervalue = 0;
2043  memset(temp, '\0', sizeof(temp));
2044
2045  if ((!strcmp(Attribute, "objectSid")) ||
2046      (!strcmp(Attribute, "objectGUID")))
2047    use_bervalue = 1;
2048 
2049  if (use_bervalue)
2050    {
2051      ber_value = ldap_get_values_len(ldap_handle, ldap_entry, Attribute);
2052      Ptr = (void **)ber_value;
2053      str_value = NULL;
2054    }
2055  else
2056    {
2057      str_value = ldap_get_values(ldap_handle, ldap_entry, Attribute);
2058      Ptr = (void **)str_value;
2059      ber_value = NULL;
2060    }
2061
2062  if (Ptr != NULL)
2063    {
2064      for (; *Ptr; Ptr++)
2065        {
2066          if ((linklist_previous = calloc(1, sizeof(LK_ENTRY))) == NULL)
2067            return(1);
2068
2069          memset(linklist_previous, '\0', sizeof(LK_ENTRY));
2070          linklist_previous->next = (*linklist_current);
2071          (*linklist_current) = linklist_previous;
2072         
2073          if (((*linklist_current)->attribute = calloc(1,
2074                                              strlen(Attribute) + 1)) == NULL)
2075            return(1);
2076
2077          memset((*linklist_current)->attribute, '\0', strlen(Attribute) + 1);
2078          strcpy((*linklist_current)->attribute, Attribute);
2079
2080          if (use_bervalue)
2081            {
2082              ber_length = (*(LDAP_BERVAL **)Ptr)->bv_len;
2083
2084              if (((*linklist_current)->value = calloc(1, ber_length)) == NULL)
2085                return(1);
2086
2087              memset((*linklist_current)->value, '\0', ber_length);
2088              memcpy((*linklist_current)->value,
2089                     (*(LDAP_BERVAL **)Ptr)->bv_val, ber_length);
2090              (*linklist_current)->length = ber_length;
2091            }
2092          else
2093            {
2094              if (((*linklist_current)->value = calloc(1,
2095                                                    strlen(*Ptr) + 1)) == NULL)
2096                return(1);
2097
2098              memset((*linklist_current)->value, '\0', strlen(*Ptr) + 1);
2099              (*linklist_current)->length = strlen(*Ptr);
2100              strcpy((*linklist_current)->value, *Ptr);
2101            }
2102
2103          (*linklist_current)->ber_value = use_bervalue;
2104
2105          if (((*linklist_current)->dn = calloc(1,
2106                                      strlen(distinguished_name) + 1)) == NULL)
2107            return(1);
2108
2109          memset((*linklist_current)->dn, '\0',
2110                 strlen(distinguished_name) + 1);
2111          strcpy((*linklist_current)->dn, distinguished_name);
2112
2113#ifdef LDAP_DEBUG
2114          if (!strcmp(Attribute, "objectGUID"))
2115            {
2116              guid = (GUID *)((*linklist_current)->value);
2117              sprintf(temp,
2118                      "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
2119                      guid->Data1, guid->Data2, guid->Data3,
2120                      guid->Data4[0], guid->Data4[1], guid->Data4[2],
2121                      guid->Data4[3], guid->Data4[4], guid->Data4[5],
2122                      guid->Data4[6], guid->Data4[7]);
2123              print_to_screen("     %20s : {%s}\n", Attribute, temp);
2124            }
2125          else if (!strcmp(Attribute, "objectSid"))
2126            {
2127              sid = (SID *)((*(LDAP_BERVAL **)Ptr)->bv_val);
2128
2129#ifdef _WIN32
2130              print_to_screen("        Revision = %d\n", sid->Revision);
2131              print_to_screen("        SID Identifier Authority:\n");
2132              sid_auth = &sid->IdentifierAuthority;
2133              if (sid_auth->Value[0])
2134                print_to_screen("            SECURITY_NULL_SID_AUTHORITY\n");
2135              else if (sid_auth->Value[1])
2136                print_to_screen("            SECURITY_WORLD_SID_AUTHORITY\n");
2137              else if (sid_auth->Value[2])
2138                print_to_screen("            SECURITY_LOCAL_SID_AUTHORITY\n");
2139              else if (sid_auth->Value[3])
2140                print_to_screen("           SECURITY_CREATOR_SID_AUTHORITY\n");
2141              else if (sid_auth->Value[5])
2142                print_to_screen("            SECURITY_NT_AUTHORITY\n");
2143              else
2144                print_to_screen("            UNKNOWN SID AUTHORITY\n");
2145              subauth_count = GetSidSubAuthorityCount(sid);
2146              print_to_screen("        SidSubAuthorityCount = %d\n",
2147                              *subauth_count);
2148              print_to_screen("        SidSubAuthority:\n");
2149              for (i = 0; i < *subauth_count; i++)
2150                {
2151                  if ((subauth = GetSidSubAuthority(sid, i)) != NULL)
2152                    print_to_screen("            %u\n", *subauth);
2153                }
2154#endif
2155            }
2156          else if ((!memcmp(Attribute, "userAccountControl",
2157                            strlen("userAccountControl"))) ||
2158                   (!memcmp(Attribute, "sAMAccountType",
2159                            strlen("sAmAccountType"))))
2160            {
2161              intValue = atoi(*Ptr);
2162              print_to_screen("     %20s : %ld\n",Attribute, intValue);
2163
2164              if (!memcmp(Attribute, "userAccountControl",
2165                          strlen("userAccountControl")))
2166                {
2167                  if (intValue & UF_ACCOUNTDISABLE)
2168                    print_to_screen("     %20s :    %s\n",
2169                                    "", "Account disabled");
2170                  else
2171                    print_to_screen("     %20s :    %s\n",
2172                                    "", "Account active");
2173                  if (intValue & UF_HOMEDIR_REQUIRED)
2174                    print_to_screen("     %20s :    %s\n",
2175                                    "", "Home directory required");
2176                  if (intValue & UF_LOCKOUT)
2177                    print_to_screen("     %20s :    %s\n",
2178                                    "", "Account locked out");
2179                  if (intValue & UF_PASSWD_NOTREQD)
2180                    print_to_screen("     %20s :    %s\n",
2181                                    "", "No password required");
2182                  if (intValue & UF_PASSWD_CANT_CHANGE)
2183                    print_to_screen("     %20s :    %s\n",
2184                                    "", "Cannot change password");
2185                  if (intValue & UF_TEMP_DUPLICATE_ACCOUNT)
2186                    print_to_screen("     %20s :    %s\n",
2187                                    "", "Temp duplicate account");
2188                  if (intValue & UF_NORMAL_ACCOUNT)
2189                    print_to_screen("     %20s :    %s\n",
2190                                    "", "Normal account");
2191                  if (intValue & UF_INTERDOMAIN_TRUST_ACCOUNT)
2192                    print_to_screen("     %20s :    %s\n",
2193                                    "", "Interdomain trust account");
2194                  if (intValue & UF_WORKSTATION_TRUST_ACCOUNT)
2195                    print_to_screen("     %20s :    %s\n",
2196                                    "", "Workstation trust account");
2197                  if (intValue & UF_SERVER_TRUST_ACCOUNT)
2198                    print_to_screen("     %20s :    %s\n",
2199                                    "", "Server trust account");
2200                }
2201            }
2202          else
2203            {
2204              print_to_screen("     %20s : %s\n",Attribute, *Ptr);
2205            }
2206#endif /*LDAP_DEBUG*/
2207        }
2208
2209      if (str_value != NULL)
2210        ldap_value_free(str_value);
2211
2212      if (ber_value != NULL)
2213        ldap_value_free_len(ber_value);
2214    }
2215
2216  (*linklist_current) = linklist_previous;
2217
2218  return(0);
2219}
2220
2221int moira_connect(void)
2222{
2223  long    rc;
2224  char    HostName[64];
2225
2226  if (!mr_connections++)
2227    {
2228
2229#ifdef _WIN32
2230      memset(HostName, '\0', sizeof(HostName));
2231      strcpy(HostName, "ttsp");
2232      rc = mr_connect_cl(HostName, "ldap.incr", QUERY_VERSION, 1);
2233#else
2234      struct utsname uts;
2235      uname(&uts);
2236      rc = mr_connect_cl(uts.nodename, "ldap.incr", QUERY_VERSION, 1);
2237#endif /*WIN32*/
2238
2239      return rc;
2240    }
2241
2242  return 0;
2243}
2244
2245int check_winad(void)
2246{
2247  int i;
2248 
2249  for (i = 0; file_exists(STOP_FILE); i++)
2250    {
2251      if (i > 30)
2252        {
2253          critical_alert(whoami, "Ldap incremental",
2254                         "Ldap incremental failed (%s exists): %s",
2255                         STOP_FILE, tbl_buf);
2256          return(1);
2257        }
2258
2259      sleep(60);
2260    }
2261
2262  return(0);
2263}
2264
2265int moira_disconnect(void)
2266{
2267
2268  if (!--mr_connections)
2269    {
2270      mr_disconnect();
2271    }
2272
2273  return 0;
2274}
2275
2276void get_distinguished_name(LDAP *ldap_handle, LDAPMessage *ldap_entry,
2277                            char *distinguished_name)
2278{
2279  char    *CName;
2280 
2281  CName = ldap_get_dn(ldap_handle, ldap_entry);
2282
2283  if (CName == NULL)
2284    return;
2285
2286  strcpy(distinguished_name, CName);
2287  ldap_memfree(CName);
2288}
2289
2290int linklist_create_entry(char *attribute, char *value,
2291                          LK_ENTRY **linklist_entry)
2292{
2293  (*linklist_entry) = calloc(1, sizeof(LK_ENTRY));
2294
2295  if (!(*linklist_entry))
2296    {
2297      return(1);
2298    }
2299
2300  memset((*linklist_entry), '\0', sizeof(LK_ENTRY));
2301  (*linklist_entry)->attribute = calloc(1, strlen(attribute) + 1);
2302  memset((*linklist_entry)->attribute, '\0', strlen(attribute) + 1);
2303  strcpy((*linklist_entry)->attribute, attribute);
2304  (*linklist_entry)->value = calloc(1, strlen(value) + 1);
2305  memset((*linklist_entry)->value, '\0', strlen(value) + 1);
2306  strcpy((*linklist_entry)->value, value);
2307  (*linklist_entry)->length = strlen(value);
2308  (*linklist_entry)->next = NULL;
2309
2310  return(0);
2311}
2312
2313void print_to_screen(const char *fmt, ...)
2314{
2315  va_list pvar;
2316
2317  va_start(pvar, fmt);
2318  vfprintf(stderr, fmt, pvar);
2319  fflush(stderr);
2320  va_end(pvar);
2321}
2322
2323int get_group_membership(char *group_membership, char *group_ou,
2324                         int *security_flag, char **av)
2325{
2326  int  maillist_flag;
2327  int  group_flag;
2328 
2329  maillist_flag = atoi(av[L_MAILLIST]);
2330  group_flag = atoi(av[L_GROUP]);
2331
2332  if (security_flag != NULL)
2333    (*security_flag) = 0;
2334 
2335  if ((maillist_flag) && (group_flag))
2336    {
2337      if (group_membership != NULL)
2338        group_membership[0] = 'B';
2339
2340      if (security_flag != NULL)
2341        (*security_flag) = 1;
2342
2343      if (group_ou != NULL)
2344        strcpy(group_ou, group_ou_both);
2345    }
2346  else if ((!maillist_flag) && (group_flag))
2347    {
2348      if (group_membership != NULL)
2349        group_membership[0] = 'S';
2350
2351      if (security_flag != NULL)
2352        (*security_flag) = 1;
2353
2354      if (group_ou != NULL)
2355        strcpy(group_ou, group_ou_security);
2356    }
2357  else if ((maillist_flag) && (!group_flag))
2358    {
2359      if (group_membership != NULL)
2360        group_membership[0] = 'D';
2361
2362      if (group_ou != NULL)
2363        strcpy(group_ou, group_ou_distribution);
2364    }
2365  else
2366    {
2367      if (group_membership != NULL)
2368        group_membership[0] = 'N';
2369
2370      if (group_ou != NULL)
2371        strcpy(group_ou, group_ou_neither);
2372    }
2373
2374  return(0);
2375}
2376
2377int group_rename(LDAP *ldap_handle, char *dn_path,
2378                 char *before_group_name, char *before_group_membership,
2379                 char *before_group_ou, int before_security_flag,
2380                 char *before_desc, char *after_group_name,
2381                 char *after_group_membership, char *after_group_ou,
2382                 int after_security_flag, char *after_desc,
2383                 char *MoiraId, char *filter, char *maillist, char *nfsgroup)
2384{
2385  LDAPMod   *mods[20];
2386  char      old_dn[512];
2387  char      new_dn[512];
2388  char      new_dn_path[512];
2389  char      sam_name[256];
2390  char      mail[256];
2391  char      mail_nickname[256];
2392  char      proxy_address[256];
2393  char      address_book[256];
2394  char      *attr_array[3];
2395  char      *mitMoiraId_v[] = {NULL, NULL};
2396  char      *name_v[] = {NULL, NULL};
2397  char      *samAccountName_v[] = {NULL, NULL};
2398  char      *groupTypeControl_v[] = {NULL, NULL};
2399  char      *mail_v[] = {NULL, NULL};
2400  char      *proxy_address_v[] = {NULL, NULL};
2401  char      *mail_nickname_v[] = {NULL, NULL};
2402  char      *report_to_originator_v[] = {NULL, NULL};
2403  char      *address_book_v[] = {NULL, NULL};
2404  char      *legacy_exchange_dn_v[] = {NULL, NULL};
2405  char      *null_v[] = {NULL, NULL};
2406  u_int     groupTypeControl;
2407  char      groupTypeControlStr[80];
2408  char      contact_mail[256];
2409  int       n;
2410  int       i;
2411  int       rc;
2412  LK_ENTRY  *group_base;
2413  int       group_count;
2414  int       MailDisabled = 0;
2415  char      search_filter[1024];
2416
2417  if(UseGroupUniversal)
2418    groupTypeControl = ADS_GROUP_TYPE_UNIVERSAL_GROUP;
2419  else
2420    groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
2421     
2422  if (!check_string(before_group_name))
2423    {
2424      com_err(whoami, 0,
2425              "Unable to process invalid LDAP list name %s",
2426              before_group_name);
2427      return(AD_INVALID_NAME);
2428    }
2429
2430  if (!check_string(after_group_name))
2431    {
2432      com_err(whoami, 0,
2433              "Unable to process invalid LDAP list name %s", after_group_name);
2434      return(AD_INVALID_NAME);
2435    }
2436
2437  if (Exchange)
2438    {
2439      if(atoi(maillist))
2440        {
2441          group_count = 0;
2442          group_base = NULL;
2443         
2444          sprintf(search_filter, "(&(objectClass=user)(homeMDB=*)(cn=%s))",
2445                  after_group_name);
2446          attr_array[0] = "cn";
2447          attr_array[1] = NULL;
2448
2449          if ((rc = linklist_build(ldap_handle, dn_path, search_filter,
2450                                   attr_array, &group_base, &group_count,
2451                                   LDAP_SCOPE_SUBTREE)) != 0)
2452          {
2453            com_err(whoami, 0, "Unable to process group %s : %s",
2454                    after_group_name, ldap_err2string(rc));
2455            return(rc);
2456          }
2457         
2458          if (group_count)
2459            {
2460              com_err(whoami, 0, "Object already exists with name %s",
2461                      after_group_name);
2462              MailDisabled++;
2463            }
2464       
2465          linklist_free(group_base);
2466          group_base = NULL;
2467          group_count = 0;
2468        }
2469    }
2470
2471  group_count = 0;
2472  group_base = NULL;
2473
2474  if (rc = ad_get_group(ldap_handle, dn_path, before_group_name,
2475                        before_group_membership,
2476                        MoiraId, "samAccountName", &group_base,
2477                        &group_count, filter))
2478    return(rc);
2479
2480  if (group_count == 0)
2481    {
2482      return(AD_NO_GROUPS_FOUND);
2483    }
2484
2485  if (group_count != 1)
2486    {
2487      com_err(whoami, 0, "Unable to process multiple groups with "
2488              "MoiraId = %s exist in the directory", MoiraId);
2489      return(AD_MULTIPLE_GROUPS_FOUND);
2490    }
2491
2492  strcpy(old_dn, group_base->dn);
2493
2494  linklist_free(group_base);
2495  group_base = NULL;
2496  group_count = 0;
2497  attr_array[0] = "sAMAccountName";
2498  attr_array[1] = NULL;
2499
2500  if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
2501                           &group_base, &group_count,
2502                           LDAP_SCOPE_SUBTREE)) != 0)
2503    {
2504      com_err(whoami, 0, "Unable to get list %s dn : %s",
2505              after_group_name, ldap_err2string(rc));
2506      return(rc);
2507    }
2508
2509  if (group_count != 1)
2510    {
2511      com_err(whoami, 0,
2512              "Unable to get sAMAccountName for group %s",
2513              before_group_name);
2514      return(AD_LDAP_FAILURE);
2515    }
2516 
2517  strcpy(sam_name, group_base->value);
2518  linklist_free(group_base);
2519  group_base = NULL;
2520  group_count = 0;
2521 
2522  sprintf(new_dn_path, "%s,%s", after_group_ou, dn_path);
2523  sprintf(new_dn, "cn=%s", after_group_name);
2524  sprintf(mail, "%s@%s", after_group_name, lowercase(ldap_domain));
2525  sprintf(contact_mail, "%s@mit.edu", after_group_name);
2526  sprintf(proxy_address, "SMTP:%s@%s", after_group_name,
2527          lowercase(ldap_domain));
2528  sprintf(mail_nickname, "%s", after_group_name);
2529
2530  com_err(whoami, 0, "Old %s New %s,%s", old_dn, new_dn, new_dn_path);
2531
2532  if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, new_dn_path,
2533                              TRUE, NULL, NULL)) != LDAP_SUCCESS)
2534    {
2535      com_err(whoami, 0, "Unable to rename list from %s to %s : %s",
2536              before_group_name, after_group_name, ldap_err2string(rc));
2537      return(rc);
2538    }
2539 
2540  name_v[0] = after_group_name;
2541
2542  if (!strncmp(&sam_name[strlen(sam_name) - strlen(group_suffix)],
2543               group_suffix, strlen(group_suffix)))
2544    {
2545      sprintf(sam_name, "%s%s", after_group_name, group_suffix);
2546    }
2547  else
2548    {
2549      com_err(whoami, 0,
2550              "Unable to rename list from %s to %s : sAMAccountName not found",
2551              before_group_name, after_group_name);
2552      return(rc);
2553    }
2554
2555  samAccountName_v[0] = sam_name;
2556
2557  if (after_security_flag)
2558    groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
2559
2560  sprintf(groupTypeControlStr, "%ld", groupTypeControl);
2561  groupTypeControl_v[0] = groupTypeControlStr;
2562  mitMoiraId_v[0] = MoiraId;
2563
2564  sprintf(new_dn, "cn=%s,%s,%s", after_group_name, after_group_ou, dn_path);
2565  rc = attribute_update(ldap_handle, new_dn, after_desc, "description",
2566                        after_group_name);
2567  n = 0;
2568  ADD_ATTR("samAccountName", samAccountName_v, LDAP_MOD_REPLACE);
2569  ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
2570  ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2571  ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_REPLACE);
2572
2573  if (Exchange)
2574    {
2575      if(atoi(maillist) && !MailDisabled && email_isvalid(mail))
2576        {
2577          mail_nickname_v[0] = mail_nickname;
2578          proxy_address_v[0] = proxy_address;
2579          mail_v[0] = mail;
2580          report_to_originator_v[0] = "TRUE";
2581
2582          ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
2583          ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2584          ADD_ATTR("proxyAddresses", proxy_address_v, LDAP_MOD_REPLACE);
2585          ADD_ATTR("reportToOriginator", report_to_originator_v,
2586                   LDAP_MOD_REPLACE);
2587        }
2588      else
2589        {
2590          mail_nickname_v[0] = NULL;
2591          proxy_address_v[0] = NULL;
2592          mail_v[0] = NULL;
2593          legacy_exchange_dn_v[0] = NULL;
2594          address_book_v[0] = NULL;
2595          report_to_originator_v[0] = NULL;
2596
2597          ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
2598          ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2599          ADD_ATTR("proxyAddresses", proxy_address_v, LDAP_MOD_REPLACE);
2600          ADD_ATTR("legacyExchangeDN", legacy_exchange_dn_v, LDAP_MOD_REPLACE);
2601          ADD_ATTR("showInAddressBook", address_book_v, LDAP_MOD_REPLACE);
2602          ADD_ATTR("reportToOriginator", report_to_originator_v,
2603                   LDAP_MOD_REPLACE);
2604        }
2605    }
2606  else
2607    {
2608      if(atoi(maillist) && email_isvalid(contact_mail))
2609        {
2610          mail_v[0] = contact_mail;
2611          ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2612
2613          if(!ActiveDirectory)
2614            {
2615              null_v[0] = "/dev/null";
2616              ADD_ATTR("mailRoutingAddress", null_v, LDAP_MOD_REPLACE);
2617              ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_REPLACE);
2618            }
2619        }
2620    }
2621
2622  mods[n] = NULL;
2623
2624  if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
2625    {
2626      com_err(whoami, 0,
2627              "Unable to modify list data for %s after renaming: %s",
2628              after_group_name, ldap_err2string(rc));
2629    }
2630
2631  for (i = 0; i < n; i++)
2632    free(mods[i]);
2633
2634  return(rc);
2635}
2636
2637int group_create(int ac, char **av, void *ptr)
2638{
2639  LDAPMod *mods[20];
2640  char new_dn[256];
2641  char group_ou[256];
2642  char new_group_name[256];
2643  char sam_group_name[256];
2644  char cn_group_name[256];
2645  char mail[256];
2646  char contact_mail[256];
2647  char mail_nickname[256];
2648  char proxy_address[256];
2649  char address_book[256];
2650  char *cn_v[] = {NULL, NULL};
2651  char *objectClass_v[] = {"top", "group", NULL};
2652  char *objectClass_ldap_v[] = {"top", "microsoftComTop", "securityPrincipal",
2653                                "group", "mailRecipient", NULL};
2654  char info[256];
2655  char *samAccountName_v[] = {NULL, NULL};
2656  char *altSecurityIdentities_v[] = {NULL, NULL};
2657  char *member_v[] = {NULL, NULL};
2658  char *name_v[] = {NULL, NULL};
2659  char *desc_v[] = {NULL, NULL};
2660  char *info_v[] = {NULL, NULL};
2661  char *mitMoiraId_v[] = {NULL, NULL};
2662  char *mitMoiraPublic_v[] = {NULL, NULL};
2663  char *mitMoiraHidden_v[] = {NULL, NULL};
2664  char *mitMoiraActive_v[] = {NULL, NULL};
2665  char *mitMoiraNFSGroup_v[] = {NULL, NULL};
2666  char *groupTypeControl_v[] = {NULL, NULL};
2667  char *mail_v[] = {NULL, NULL};
2668  char *proxy_address_v[] = {NULL, NULL};
2669  char *mail_nickname_v[] = {NULL, NULL};
2670  char *report_to_originator_v[] = {NULL, NULL};
2671  char *address_book_v[] = {NULL, NULL};
2672  char *legacy_exchange_dn_v[] = {NULL, NULL};
2673  char *gidNumber_v[] = {NULL, NULL};
2674  char *null_v[] = {NULL, NULL};
2675  char groupTypeControlStr[80];
2676  char group_membership[1];
2677  int  i;
2678  int  security_flag;
2679  u_int groupTypeControl;
2680  int  n;
2681  int  rc;
2682  int  updateGroup;
2683  int  MailDisabled = 0;
2684  char **call_args;
2685  LK_ENTRY *group_base;
2686  int  group_count;
2687  char filter[1024];
2688  char *attr_array[3];
2689 
2690  call_args = ptr;
2691
2692  if(UseGroupUniversal)
2693    groupTypeControl = ADS_GROUP_TYPE_UNIVERSAL_GROUP;
2694  else
2695    groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
2696
2697  if (!check_string(av[L_NAME]))
2698    {
2699      com_err(whoami, 0, "Unable to process invalid LDAP list name %s",
2700              av[L_NAME]);
2701      return(AD_INVALID_NAME);
2702    }
2703
2704  updateGroup = (int)(long)call_args[4];
2705  memset(group_ou, 0, sizeof(group_ou));
2706  memset(group_membership, 0, sizeof(group_membership));
2707  security_flag = 0;
2708
2709  get_group_membership(group_membership, group_ou, &security_flag, av);
2710
2711  strcpy(new_group_name, av[L_NAME]);
2712  sprintf(new_dn, "cn=%s,%s,%s", new_group_name, group_ou, call_args[1]);
2713  sprintf(contact_mail, "%s@mit.edu", av[L_NAME]);
2714  sprintf(mail, "%s@%s", av[L_NAME], lowercase(ldap_domain));
2715  sprintf(mail_nickname, "%s", av[L_NAME]);
2716
2717  if (security_flag)
2718    groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
2719 
2720  sprintf(sam_group_name, "%s%s", av[L_NAME], group_suffix);
2721
2722  if (!updateGroup)
2723    {
2724      sprintf(groupTypeControlStr, "%ld", groupTypeControl);
2725      groupTypeControl_v[0] = groupTypeControlStr;
2726
2727      strcpy(cn_group_name, av[L_NAME]);
2728     
2729      samAccountName_v[0] = sam_group_name;
2730      name_v[0] = new_group_name;
2731      cn_v[0] = new_group_name;
2732
2733      n = 0;
2734      ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
2735
2736      if(ActiveDirectory)
2737        {
2738          ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2739        }
2740      else
2741        {
2742          mitMoiraPublic_v[0] = av[L_PUBLIC];
2743          mitMoiraHidden_v[0] = av[L_HIDDEN];
2744          mitMoiraActive_v[0] = av[L_ACTIVE];
2745          mitMoiraNFSGroup_v[0] = av[L_NFSGROUP];
2746          ADD_ATTR("objectClass", objectClass_ldap_v, LDAP_MOD_ADD);
2747          ADD_ATTR("mitMoiraPublic", mitMoiraPublic_v, LDAP_MOD_ADD);
2748          ADD_ATTR("mitMoiraHidden", mitMoiraHidden_v, LDAP_MOD_ADD);
2749          ADD_ATTR("mitMoiraActive", mitMoiraActive_v, LDAP_MOD_ADD);
2750          ADD_ATTR("mitMoiraNFSGroup", mitMoiraNFSGroup_v, LDAP_MOD_ADD);
2751         
2752          if(atoi(av[L_GROUP]))
2753            {
2754              gidNumber_v[0] = av[L_GID];
2755              ADD_ATTR("gidNumber", gidNumber_v, LDAP_MOD_ADD);
2756            }
2757        }
2758
2759      ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
2760      ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2761      ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2762
2763      if (Exchange)
2764        {
2765          if(atoi(av[L_MAILLIST]))
2766            {
2767              group_count = 0;
2768              group_base = NULL;
2769             
2770              sprintf(filter, "(&(objectClass=user)(homeMDB=*)(cn=%s))",
2771                      av[L_NAME]);
2772              attr_array[0] = "cn";
2773              attr_array[1] = NULL;
2774             
2775              if ((rc = linklist_build((LDAP *)call_args[0], call_args[1],
2776                                       filter, attr_array, &group_base,
2777                                       &group_count,
2778                                       LDAP_SCOPE_SUBTREE)) != 0)
2779                {
2780                  com_err(whoami, 0, "Unable to process group %s : %s",
2781                          av[L_NAME], ldap_err2string(rc));
2782                  return(rc);
2783                }
2784             
2785              if (group_count)
2786                {
2787                  com_err(whoami, 0, "Object already exists with name %s",
2788                          av[L_NAME]);
2789                  MailDisabled++;
2790                }
2791       
2792              linklist_free(group_base);
2793              group_base = NULL;
2794              group_count = 0;
2795            }
2796         
2797          if(atoi(av[L_MAILLIST]) && !MailDisabled && email_isvalid(mail))
2798            {
2799              mail_nickname_v[0] = mail_nickname;
2800              report_to_originator_v[0] = "TRUE";
2801
2802              ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_ADD);
2803              ADD_ATTR("reportToOriginator", report_to_originator_v,
2804                       LDAP_MOD_ADD);
2805            }
2806        }
2807      else
2808        {
2809          if(atoi(av[L_MAILLIST]) && email_isvalid(contact_mail))
2810            {
2811              mail_v[0] = contact_mail;
2812              ADD_ATTR("mail", mail_v, LDAP_MOD_ADD);
2813
2814              if(!ActiveDirectory)
2815                {
2816                  null_v[0] = "/dev/null";
2817                  ADD_ATTR("mailRoutingAddress", null_v, LDAP_MOD_ADD);
2818                  ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_ADD);
2819                }
2820            }
2821        }
2822     
2823      if (strlen(av[L_DESC]) != 0)
2824        {
2825          desc_v[0] = av[L_DESC];
2826          ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2827        }
2828     
2829      ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_ADD);
2830
2831      if (strlen(av[L_ACE_NAME]) != 0)
2832        {
2833          sprintf(info, "The Administrator of this list is: %s",
2834                  av[L_ACE_NAME]);
2835          info_v[0] = info;
2836          ADD_ATTR("info", info_v, LDAP_MOD_ADD);
2837        }
2838
2839      if (strlen(call_args[5]) != 0)
2840        {
2841          mitMoiraId_v[0] = call_args[5];
2842          ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
2843        }
2844         
2845      mods[n] = NULL;
2846     
2847      rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
2848     
2849      for (i = 0; i < n; i++)
2850        free(mods[i]);
2851
2852      if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2853        {
2854          com_err(whoami, 0, "Unable to create list %s in directory : %s",
2855                  av[L_NAME], ldap_err2string(rc));
2856          callback_rc = rc;
2857          return(rc);
2858        }
2859    }
2860
2861  if ((rc == LDAP_ALREADY_EXISTS) || (updateGroup))
2862    {
2863      rc = attribute_update((LDAP *)call_args[0], new_dn, av[L_DESC],
2864                            "description", av[L_NAME]);
2865      sprintf(info, "The Administrator of this list is: %s", av[L_ACE_NAME]);
2866
2867      rc = attribute_update((LDAP *)call_args[0], new_dn, info, "info",
2868                                av[L_NAME]);
2869
2870      n = 0;
2871
2872      if (strlen(call_args[5]) != 0)
2873        {
2874          mitMoiraId_v[0] = call_args[5];
2875          ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2876        }
2877
2878      if (!(atoi(av[L_ACTIVE])))
2879        {
2880          member_v[0] = NULL;
2881          ADD_ATTR("member", member_v, LDAP_MOD_REPLACE);
2882        }
2883   
2884      if (!ActiveDirectory)
2885        {
2886          mitMoiraPublic_v[0] = av[L_PUBLIC];
2887          mitMoiraHidden_v[0] = av[L_HIDDEN];
2888          mitMoiraActive_v[0] = av[L_ACTIVE];
2889          mitMoiraNFSGroup_v[0] = av[L_NFSGROUP];
2890          ADD_ATTR("mitMoiraPublic", mitMoiraPublic_v, LDAP_MOD_REPLACE);
2891          ADD_ATTR("mitMoiraHidden", mitMoiraHidden_v, LDAP_MOD_REPLACE);
2892          ADD_ATTR("mitMoiraActive", mitMoiraActive_v, LDAP_MOD_REPLACE);
2893          ADD_ATTR("mitMoiraNFSGroup", mitMoiraNFSGroup_v, LDAP_MOD_REPLACE);
2894         
2895          if(atoi(av[L_GROUP]))
2896            {
2897              gidNumber_v[0] = av[L_GID];
2898              ADD_ATTR("gidNumber", gidNumber_v, LDAP_MOD_REPLACE);
2899            }
2900          else
2901            {
2902              ADD_ATTR("gidNumber", gidNumber_v, LDAP_MOD_REPLACE);
2903            }
2904        }
2905
2906      if (Exchange)
2907        {
2908          if(atoi(av[L_MAILLIST]))
2909            {
2910              group_count = 0;
2911              group_base = NULL;
2912             
2913              sprintf(filter, "(&(objectClass=user)(homeMDB=*)(cn=%s))",
2914                      av[L_NAME]);
2915              attr_array[0] = "cn";
2916              attr_array[1] = NULL;
2917             
2918              if ((rc = linklist_build((LDAP *)call_args[0], call_args[1],
2919                                       filter, attr_array, &group_base,
2920                                       &group_count,
2921                                       LDAP_SCOPE_SUBTREE)) != 0)
2922                {
2923                  com_err(whoami, 0, "Unable to process group %s : %s",
2924                          av[L_NAME], ldap_err2string(rc));
2925                  return(rc);
2926                }
2927             
2928              if (group_count)
2929                {
2930                  com_err(whoami, 0, "Object already exists with name %s",
2931                          av[L_NAME]);
2932                  MailDisabled++;
2933                }
2934             
2935              linklist_free(group_base);
2936              group_base = NULL;
2937              group_count = 0;
2938            }
2939
2940          if (atoi(av[L_MAILLIST]) && !MailDisabled && email_isvalid(mail))
2941            {
2942              mail_nickname_v[0] = mail_nickname;
2943              report_to_originator_v[0] = "TRUE";
2944
2945              ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
2946              ADD_ATTR("reportToOriginator", report_to_originator_v,
2947                       LDAP_MOD_REPLACE);
2948            }
2949          else
2950            {
2951              mail_v[0] = NULL;
2952              mail_nickname_v[0] = NULL;
2953              proxy_address_v[0] = NULL;
2954              legacy_exchange_dn_v[0] = NULL;
2955              address_book_v[0] = NULL;
2956              report_to_originator_v[0] = NULL;
2957
2958              ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
2959              ADD_ATTR("proxyAddresses", proxy_address_v, LDAP_MOD_REPLACE);
2960              ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2961              ADD_ATTR("legacyExchangeDN", legacy_exchange_dn_v,
2962                       LDAP_MOD_REPLACE);
2963              ADD_ATTR("showInAddressBook", address_book_v, LDAP_MOD_REPLACE);
2964              ADD_ATTR("reportToOriginator", report_to_originator_v,
2965                       LDAP_MOD_REPLACE);
2966            }
2967        }
2968      else
2969        {
2970          if (atoi(av[L_MAILLIST]) && email_isvalid(contact_mail))
2971            {
2972              mail_v[0] = contact_mail;
2973              ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2974
2975              if(!ActiveDirectory)
2976                {
2977                  null_v[0] = "/dev/null";
2978                  ADD_ATTR("mailRoutingAddress", null_v, LDAP_MOD_REPLACE);
2979                  ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_REPLACE);
2980                }
2981            }
2982          else
2983            {
2984              mail_v[0] = NULL;
2985              ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2986
2987              if(!ActiveDirectory)
2988                {
2989                  null_v[0] = NULL;
2990                  ADD_ATTR("mailRoutingAddress", null_v, LDAP_MOD_REPLACE);
2991                  ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_REPLACE);
2992                }
2993            }
2994        }
2995   
2996      mods[n] = NULL;
2997      rc = LDAP_SUCCESS;
2998
2999      if (n != 0)
3000        {
3001          rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
3002
3003          for (i = 0; i < n; i++)
3004              free(mods[i]);
3005
3006          if (rc != LDAP_SUCCESS)
3007            {
3008              com_err(whoami, 0, "Unable to update list %s in directory : %s",
3009                      av[L_NAME], ldap_err2string(rc));
3010              callback_rc = rc;
3011              return(rc);
3012            }
3013        }
3014    }
3015
3016  ProcessGroupSecurity((LDAP *)call_args[0], call_args[1], av[L_NAME],
3017                       atoi(av[L_HIDDEN]),  av[L_ACE_TYPE], av[L_ACE_NAME]);
3018
3019  return(LDAP_SUCCESS);
3020}
3021
3022int ProcessGroupSecurity(LDAP *ldap_handle, char *dn_path,
3023                         char *TargetGroupName, int HiddenGroup,
3024                         char *AceType, char *AceName)
3025{
3026  char          filter_exp[1024];
3027  char          *attr_array[5];
3028  char          search_path[512];
3029  char          root_ou[128];
3030  char          TemplateDn[512];
3031  char          TemplateSamName[128];
3032  char          TargetDn[512];
3033  char          TargetSamName[128];
3034  char          AceSamAccountName[128];
3035  char          AceDn[256];
3036  unsigned char AceSid[128];
3037  unsigned char UserTemplateSid[128];
3038  char          acBERBuf[N_SD_BER_BYTES];
3039  char          GroupSecurityTemplate[256];
3040  char          hide_addres_lists[256];
3041  char          address_book[256];
3042  char          *hide_address_lists_v[] = {NULL, NULL};
3043  char          *address_book_v[] = {NULL, NULL};
3044  char          *owner_v[] = {NULL, NULL};
3045  int           AceSidCount;
3046  int           UserTemplateSidCount;
3047  int           group_count;
3048  int           n;
3049  int           i;
3050  int           rc;
3051  int           nVal;
3052  ULONG         dwInfo;
3053  int           array_count = 0;
3054  LDAPMod       *mods[20];
3055  LK_ENTRY      *group_base;
3056  LDAP_BERVAL   **ppsValues;
3057  LDAPControl sControl = {"1.2.840.113556.1.4.801",
3058                          { N_SD_BER_BYTES, acBERBuf },
3059                          TRUE
3060                         };
3061  LDAPControl *apsServerControls[] = {&sControl, NULL};
3062  LDAPMessage *psMsg;
3063
3064  dwInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
3065    DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
3066  BEREncodeSecurityBits(dwInfo, acBERBuf);
3067
3068  sprintf(search_path, "%s,%s", group_ou_root, dn_path);
3069  sprintf(filter_exp, "(sAMAccountName=%s%s)", TargetGroupName, group_suffix);
3070  attr_array[0] = "sAMAccountName";
3071  attr_array[1] = NULL;
3072  group_count = 0;
3073  group_base = NULL;
3074
3075  if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array,
3076                           &group_base, &group_count,
3077                           LDAP_SCOPE_SUBTREE) != 0))
3078    return(1);
3079
3080  if (group_count != 1)
3081    {
3082      linklist_free(group_base);
3083      return(1);
3084    }
3085
3086  strcpy(TargetDn, group_base->dn);
3087  strcpy(TargetSamName, group_base->value);
3088  linklist_free(group_base);
3089  group_base = NULL;
3090  group_count = 0;
3091
3092  UserTemplateSidCount = 0;
3093  memset(UserTemplateSid, '\0', sizeof(UserTemplateSid));
3094  memset(AceSamAccountName, '\0', sizeof(AceSamAccountName));
3095  memset(AceSid, '\0', sizeof(AceSid));
3096  AceSidCount = 0;
3097  group_base = NULL;
3098  group_count = 0;
3099
3100  if (strlen(AceName) != 0)
3101    {
3102      if (!strcmp(AceType, "LIST"))
3103        {
3104          sprintf(AceSamAccountName, "%s%s", AceName, group_suffix);
3105          strcpy(root_ou, group_ou_root);
3106        }
3107      else if (!strcmp(AceType, "USER"))
3108        {
3109          sprintf(AceSamAccountName, "%s", AceName);
3110          strcpy(root_ou, user_ou);
3111        }
3112
3113      if (ActiveDirectory)
3114        {
3115          if (strlen(AceSamAccountName) != 0)
3116            {
3117              sprintf(search_path, "%s", dn_path);
3118              sprintf(filter_exp, "(sAMAccountName=%s)", AceSamAccountName);
3119              attr_array[0] = "objectSid";
3120              attr_array[1] = NULL;
3121              group_count = 0;
3122              group_base = NULL;
3123             
3124              if ((rc = linklist_build(ldap_handle, search_path, filter_exp,
3125                                       attr_array, &group_base, &group_count,
3126                                       LDAP_SCOPE_SUBTREE) != 0))
3127                return(1);
3128              if (group_count == 1)
3129                {
3130                  strcpy(AceDn, group_base->dn);
3131                  AceSidCount = group_base->length;
3132                  memcpy(AceSid, group_base->value, AceSidCount);
3133                }
3134              linklist_free(group_base);
3135              group_base = NULL;
3136              group_count = 0;
3137            }
3138        }
3139      else
3140        {
3141          if (strlen(AceSamAccountName) != 0)
3142            {
3143              sprintf(search_path, "%s", dn_path);
3144              sprintf(filter_exp, "(sAMAccountName=%s)", AceSamAccountName);
3145              attr_array[0] = "samAccountName";
3146              attr_array[1] = NULL;
3147              group_count = 0;
3148              group_base = NULL;
3149             
3150              if ((rc = linklist_build(ldap_handle, search_path, filter_exp,
3151                                       attr_array, &group_base, &group_count,
3152                                       LDAP_SCOPE_SUBTREE) != 0))
3153                return(1);
3154              if (group_count == 1)
3155                {
3156                  strcpy(AceDn, group_base->dn);
3157                }
3158              linklist_free(group_base);
3159              group_base = NULL;
3160              group_count = 0;
3161            }
3162        }
3163    }
3164
3165  if (!ActiveDirectory)
3166    {
3167      if (strlen(AceDn) != 0)
3168        {
3169          owner_v[0] = strdup(AceDn);
3170          n = 0;
3171          ADD_ATTR("owner", owner_v, LDAP_MOD_REPLACE);
3172
3173          mods[n] = NULL;
3174
3175          rc = ldap_modify_s(ldap_handle, TargetDn, mods);
3176         
3177          for (i = 0; i < n; i++)
3178            free(mods[i]);
3179
3180          if (rc != LDAP_SUCCESS)
3181            com_err(whoami, 0, "Unable to set owner for group %s : %s",
3182              TargetGroupName, ldap_err2string(rc));
3183        }
3184
3185      return(rc);
3186    }
3187 
3188  if (AceSidCount == 0)
3189    {
3190      com_err(whoami, 0, "Group %s: Administrator: %s, Type: %s - does not "
3191              "have a directory SID.", TargetGroupName, AceName, AceType);
3192      com_err(whoami, 0, "   Non-admin security group template will be used.");
3193    }
3194  else
3195    {
3196      sprintf(search_path, "%s,%s", security_template_ou, dn_path);
3197      sprintf(filter_exp, "(sAMAccountName=%s)", "UserTemplate.u");
3198      attr_array[0] = "objectSid";
3199      attr_array[1] = NULL;
3200
3201      group_count = 0;
3202      group_base = NULL;
3203
3204      if ((rc = linklist_build(ldap_handle, search_path, filter_exp,
3205                               attr_array, &group_base, &group_count,
3206                               LDAP_SCOPE_SUBTREE) != 0))
3207        return(1);
3208
3209      if ((rc != 0) || (group_count != 1))
3210        {
3211          com_err(whoami, 0, "Unable to process user security template: %s",
3212                  "UserTemplate");
3213          AceSidCount = 0;
3214        }
3215      else
3216        {
3217          UserTemplateSidCount = group_base->length;
3218          memcpy(UserTemplateSid, group_base->value, UserTemplateSidCount);
3219        }
3220      linklist_free(group_base);
3221      group_base = NULL;
3222      group_count = 0;
3223    }
3224
3225  if (HiddenGroup)
3226    {
3227      if (AceSidCount == 0)
3228        {
3229          strcpy(GroupSecurityTemplate, HIDDEN_GROUP);
3230          sprintf(filter_exp, "(sAMAccountName=%s)", HIDDEN_GROUP);
3231        }
3232      else
3233        {
3234          strcpy(GroupSecurityTemplate, HIDDEN_GROUP_WITH_ADMIN);
3235          sprintf(filter_exp, "(sAMAccountName=%s)", HIDDEN_GROUP_WITH_ADMIN);
3236        }
3237    }
3238  else
3239    {
3240      if (AceSidCount == 0)
3241        {
3242          strcpy(GroupSecurityTemplate, NOT_HIDDEN_GROUP);
3243          sprintf(filter_exp, "(sAMAccountName=%s)", NOT_HIDDEN_GROUP);
3244        }
3245      else
3246        {
3247          strcpy(GroupSecurityTemplate, NOT_HIDDEN_GROUP_WITH_ADMIN);
3248          sprintf(filter_exp, "(sAMAccountName=%s)",
3249                  NOT_HIDDEN_GROUP_WITH_ADMIN);
3250        }
3251    }
3252
3253  sprintf(search_path, "%s,%s", security_template_ou, dn_path);
3254  attr_array[0] = "sAMAccountName";
3255  attr_array[1] = NULL;
3256  group_count = 0;
3257  group_base = NULL;
3258
3259  if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array,
3260                           &group_base, &group_count,
3261                           LDAP_SCOPE_SUBTREE) != 0))
3262    return(1);
3263
3264  if (group_count != 1)
3265    {
3266      linklist_free(group_base);
3267      com_err(whoami, 0, "Unable to process group security template: %s - "
3268              "security not set", GroupSecurityTemplate);
3269      return(1);
3270    }
3271
3272  strcpy(TemplateDn, group_base->dn);
3273  strcpy(TemplateSamName, group_base->value);
3274  linklist_free(group_base);
3275  group_base = NULL;
3276  group_count = 0;
3277 
3278  sprintf(filter_exp, "(sAMAccountName=%s)", TemplateSamName);
3279  rc = ldap_search_ext_s(ldap_handle,
3280                         TemplateDn,
3281                         LDAP_SCOPE_SUBTREE,
3282                         filter_exp,
3283                         NULL,
3284                         0,
3285                         apsServerControls,
3286                         NULL,
3287                         NULL,
3288                         0,
3289                         &psMsg);
3290
3291  if ((psMsg = ldap_first_entry(ldap_handle, psMsg)) == NULL)
3292    {
3293      com_err(whoami, 0, "Unable to find group security template: %s - "
3294              "security not set", GroupSecurityTemplate);
3295      return(1);
3296    }
3297
3298  ppsValues = ldap_get_values_len(ldap_handle, psMsg, "ntSecurityDescriptor");
3299
3300  if (ppsValues == NULL)
3301    {
3302      com_err(whoami, 0, "Unable to find group security descriptor for group "
3303              "%s - security not set", GroupSecurityTemplate);
3304      return(1);
3305    }
3306 
3307  if (AceSidCount != 0)
3308    {
3309      for (nVal = 0; ppsValues[nVal] != NULL; nVal++)
3310        {
3311          for (i = 0;
3312               i < (int)(ppsValues[nVal]->bv_len - UserTemplateSidCount); i++)
3313            {
3314              if (!memcmp(&ppsValues[nVal]->bv_val[i], UserTemplateSid,
3315                          UserTemplateSidCount))
3316                {
3317                  memcpy(&ppsValues[nVal]->bv_val[i], AceSid, AceSidCount);
3318                  break;
3319                }
3320            }
3321        }
3322    }
3323
3324  n = 0;
3325  ADD_ATTR("ntSecurityDescriptor", (char **)ppsValues,
3326           LDAP_MOD_REPLACE | LDAP_MOD_BVALUES);
3327
3328  if (Exchange)
3329    {
3330      if(HiddenGroup)
3331        {
3332          hide_address_lists_v[0] = "TRUE";
3333          address_book_v[0] = NULL;
3334          ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
3335                   LDAP_MOD_REPLACE);
3336          ADD_ATTR("showInAddressBook", address_book_v, LDAP_MOD_REPLACE);
3337        } else {
3338          hide_address_lists_v[0] = NULL;
3339          ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
3340                   LDAP_MOD_REPLACE);
3341        }
3342    }
3343
3344  mods[n] = NULL;
3345
3346  rc = ldap_modify_s(ldap_handle, TargetDn, mods);
3347
3348  for (i = 0; i < n; i++)
3349    free(mods[i]);
3350
3351  ldap_value_free_len(ppsValues);
3352  ldap_msgfree(psMsg);
3353
3354  if (rc != LDAP_SUCCESS)
3355    {
3356      com_err(whoami, 0, "Unable to set security settings for group %s : %s",
3357              TargetGroupName, ldap_err2string(rc));
3358
3359      if (AceSidCount != 0)
3360        {
3361          com_err(whoami, 0,
3362                  "Trying to set security for group %s without admin.",
3363                  TargetGroupName);
3364
3365          if (rc = ProcessGroupSecurity(ldap_handle, dn_path, TargetGroupName,
3366                                        HiddenGroup, "", ""))
3367            {
3368              com_err(whoami, 0, "Unable to set security for group %s.",
3369                      TargetGroupName);
3370              return(rc);
3371            }
3372        }
3373      return(rc);
3374    }
3375
3376  return(rc);
3377}
3378
3379int group_delete(LDAP *ldap_handle, char *dn_path, char *group_name,
3380                 char *group_membership, char *MoiraId)
3381{
3382  LK_ENTRY  *group_base;
3383  char      temp[512];
3384  char      filter[128];
3385  int       group_count;
3386  int       rc;
3387
3388  if (!check_string(group_name))
3389    {
3390      com_err(whoami, 0,
3391              "Unable to process invalid LDAP list name %s", group_name);
3392      return(AD_INVALID_NAME);
3393    }
3394
3395  memset(filter, '\0', sizeof(filter));
3396  group_count = 0;
3397  group_base = NULL;
3398  sprintf(temp, "%s,%s", group_ou_root, dn_path);
3399
3400  if (rc = ad_get_group(ldap_handle, temp, group_name,
3401                        group_membership, MoiraId,
3402                        "samAccountName", &group_base,
3403                        &group_count, filter))
3404    return(rc);
3405
3406  if (group_count == 1)
3407    {
3408      if ((rc = ldap_delete_s(ldap_handle, group_base->dn)) != LDAP_SUCCESS)
3409        {
3410          linklist_free(group_base);
3411          com_err(whoami, 0, "Unable to delete list %s from directory : %s",
3412                  group_name, ldap_err2string(rc));
3413          return(rc);
3414        }
3415      linklist_free(group_base);
3416    }
3417  else
3418    {
3419      linklist_free(group_base);
3420      com_err(whoami, 0, "Unable to find list %s in directory.", group_name);
3421      return(AD_NO_GROUPS_FOUND);
3422    }
3423 
3424  return(0);
3425}
3426
3427int BEREncodeSecurityBits(ULONG uBits, char *pBuffer)
3428{
3429    *pBuffer++ = 0x30;
3430    *pBuffer++ = 0x03;
3431    *pBuffer++ = 0x02;
3432    *pBuffer++ = 0x00;
3433    return(N_SD_BER_BYTES);
3434}
3435
3436int process_lists(int ac, char **av, void *ptr)
3437{
3438  int   rc;
3439  int   security_flag;
3440  char  group_ou[256];
3441  char  group_membership[2];
3442  char  **call_args;
3443
3444  call_args = ptr;
3445
3446  security_flag = 0;
3447  memset(group_ou, '\0', sizeof(group_ou));
3448  memset(group_membership, '\0', sizeof(group_membership));
3449  get_group_membership(group_membership, group_ou, &security_flag, av);
3450  rc = populate_group((LDAP *)call_args[0], (char *)call_args[1],
3451                      av[L_NAME], group_ou, group_membership,
3452                      security_flag, "", 1);
3453
3454  return(0);
3455}
3456
3457int member_list_build(int ac, char **av, void *ptr)
3458{
3459  LK_ENTRY  *linklist;
3460  char      temp[1024];
3461  char      **call_args;
3462  char      *s;
3463  call_args = ptr;
3464
3465  strcpy(temp, av[ACE_NAME]);
3466  StringTrim(temp);
3467 
3468  if (!check_string(temp))
3469    return(0);
3470
3471  if (!strcmp(av[ACE_TYPE], "USER"))
3472    {
3473      if (!((int)(long)call_args[3] & MOIRA_USERS))
3474        return(0);
3475    }
3476  else if (!strcmp(av[ACE_TYPE], "STRING"))
3477    {
3478      if (Exchange)
3479        {
3480          if((s = strchr(temp, '@')) == (char *) NULL)
3481            return(0);
3482         
3483          if(!strncasecmp(&temp[strlen(temp) - 6], ".LOCAL", 6))
3484            return(0);
3485        }
3486
3487      if (!((int)(long)call_args[3] & MOIRA_STRINGS))
3488        return(0);
3489       
3490      if (contact_create((LDAP *)call_args[0], call_args[1], temp, contact_ou))
3491        return(0);
3492    }
3493  else if (!strcmp(av[ACE_TYPE], "LIST"))
3494    {
3495      if (!((int)(long)call_args[3] & MOIRA_LISTS))
3496        return(0);
3497    }
3498  else if (!strcmp(av[ACE_TYPE], "KERBEROS"))
3499    {
3500      if (!((int)(long)call_args[3] & MOIRA_KERBEROS))
3501        return(0);
3502
3503      if (contact_create((LDAP *)call_args[0], call_args[1], temp,
3504                         kerberos_ou))
3505        return(0);
3506
3507    }
3508  else if (!strcmp(av[ACE_TYPE], "MACHINE"))
3509    {
3510      if (!((int)(long)call_args[3] & MOIRA_MACHINE))
3511        return(0);
3512    }
3513  else
3514    return(0);
3515
3516  linklist = member_base;
3517
3518  while (linklist)
3519    {
3520    if (!strcasecmp(temp, linklist->member) &&
3521        !strcasecmp(av[ACE_TYPE], linklist->type))
3522      return(0);
3523
3524    linklist = linklist->next;
3525    }
3526
3527  linklist = calloc(1, sizeof(LK_ENTRY));
3528  linklist->op = 1;
3529  linklist->dn = NULL;
3530  linklist->list = calloc(1, strlen(call_args[2]) + 1);
3531  strcpy(linklist->list, call_args[2]);
3532  linklist->type = calloc(1, strlen(av[ACE_TYPE]) + 1);
3533  strcpy(linklist->type, av[ACE_TYPE]);
3534  linklist->member = calloc(1, strlen(temp) + 1);
3535  strcpy(linklist->member, temp);
3536  linklist->next = member_base;
3537  member_base = linklist;
3538
3539  return(0);
3540}
3541
3542int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name,
3543                  char *group_ou, char *group_membership, char *user_name,
3544                  char *UserOu, char *MoiraId)
3545{
3546  char        distinguished_name[1024];
3547  char        *modvalues[2];
3548  char        temp[256];
3549  char        filter[128];
3550  char        *attr_array[3];
3551  int         group_count;
3552  int         i;
3553  int         n;
3554  LDAPMod     *mods[20];
3555  LK_ENTRY    *group_base;
3556  ULONG       rc;
3557  char        *s;
3558
3559  if (max_group_members && (group_members < max_group_members))
3560    return(0);
3561
3562  if (!check_string(group_name))
3563    return(AD_INVALID_NAME);
3564
3565  if(!contains_member(ldap_handle, dn_path, group_name, UserOu,
3566                      escape_string(user_name)))
3567    return(0);
3568
3569  memset(filter, '\0', sizeof(filter));
3570  group_base = NULL;
3571  group_count = 0;
3572
3573  if (rc = ad_get_group(ldap_handle, dn_path, group_name,
3574                        group_membership, MoiraId,
3575                        "samAccountName", &group_base,
3576                        &group_count, filter))
3577    return(rc);
3578
3579  if (group_count != 1)
3580    {
3581      com_err(whoami, 0, "Unable to find list %s in directory",
3582              group_name);
3583      linklist_free(group_base);
3584      group_base = NULL;
3585      group_count = 0;
3586      goto cleanup;
3587    }
3588
3589  strcpy(distinguished_name, group_base->dn);
3590  linklist_free(group_base);
3591  group_base = NULL;
3592  group_count = 0;
3593
3594  if(ActiveDirectory)
3595    {
3596      sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
3597    }
3598  else
3599    {
3600      if(!strcmp(UserOu, user_ou))
3601        sprintf(temp, "uid=%s,%s,%s", user_name, UserOu, dn_path);
3602      else
3603        sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
3604    }
3605
3606  modvalues[0] = temp;
3607  modvalues[1] = NULL;
3608
3609  n = 0;
3610  ADD_ATTR("member", modvalues, LDAP_MOD_DELETE);
3611  mods[n] = NULL;
3612  rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
3613
3614  for (i = 0; i < n; i++)
3615    free(mods[i]);
3616
3617  if (rc == LDAP_UNWILLING_TO_PERFORM)
3618    rc = LDAP_SUCCESS;
3619
3620  if (rc != LDAP_SUCCESS)
3621    {
3622      com_err(whoami, 0, "Unable to modify list %s members : %s",
3623              group_name, ldap_err2string(rc));
3624      goto cleanup;
3625    }
3626
3627 cleanup:
3628  return(rc);
3629}
3630
3631int member_add(LDAP *ldap_handle, char *dn_path, char *group_name,
3632               char *group_ou, char *group_membership, char *user_name,
3633               char *UserOu, char *MoiraId)
3634{
3635  char        distinguished_name[1024];
3636  char        *modvalues[2];
3637  char        temp[256];
3638  char        filter[128];
3639  int         group_count;
3640  int         n;
3641  int         i;
3642  LDAPMod     *mods[20];
3643  LK_ENTRY    *group_base;
3644  ULONG       rc;
3645
3646  if (max_group_members && (group_members < max_group_members))
3647    return(0);
3648
3649  if (!check_string(group_name))
3650    return(AD_INVALID_NAME);
3651
3652  if(contains_member(ldap_handle, dn_path, group_name, UserOu, user_name) > 0)
3653    return(0);
3654
3655  rc = 0;
3656  memset(filter, '\0', sizeof(filter));
3657  group_base = NULL;
3658  group_count = 0;
3659
3660  if (rc = ad_get_group(ldap_handle, dn_path, group_name,
3661                        group_membership, MoiraId,
3662                        "samAccountName", &group_base,
3663                        &group_count, filter))
3664    return(rc);
3665
3666  if (group_count != 1)
3667    {
3668      linklist_free(group_base);
3669      group_base = NULL;
3670      group_count = 0;
3671      com_err(whoami, 0, "Unable to find list %s %d in directory",
3672              group_name, group_count);
3673      return(AD_MULTIPLE_GROUPS_FOUND);
3674    }
3675
3676  strcpy(distinguished_name, group_base->dn);
3677  linklist_free(group_base);
3678  group_base = NULL;
3679  group_count = 0;
3680
3681  if(ActiveDirectory)
3682    {
3683      sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
3684    }
3685  else
3686    {
3687      if(!strcmp(UserOu, user_ou))
3688        sprintf(temp, "uid=%s,%s,%s", user_name, UserOu, dn_path);
3689      else
3690        sprintf(temp, "cn=%s,%s,%s", user_name, UserOu, dn_path);
3691    }
3692
3693  modvalues[0] = temp;
3694  modvalues[1] = NULL;
3695
3696  n = 0;
3697  ADD_ATTR("member", modvalues, LDAP_MOD_ADD);
3698  mods[n] = NULL;
3699  rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
3700
3701  if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
3702    rc = LDAP_SUCCESS;
3703
3704  if ((!strcmp(UserOu, contact_ou)) || (!strcmp(UserOu, kerberos_ou)))
3705    {
3706      if (rc == LDAP_UNWILLING_TO_PERFORM)
3707        rc = LDAP_SUCCESS;
3708    }
3709
3710  for (i = 0; i < n; i++)
3711    free(mods[i]);
3712
3713  if (rc != LDAP_SUCCESS)
3714    {
3715      com_err(whoami, 0, "Unable to add %s to list %s as a member : %s",
3716              user_name, group_name, ldap_err2string(rc));
3717    }
3718
3719  return(rc);
3720}
3721
3722int contact_remove_email(LDAP *ld, char *bind_path,
3723                         LK_ENTRY **linklist_base, int linklist_current)
3724{
3725  LK_ENTRY  *gPtr;
3726  int       rc;
3727  char      *mail_v[] = {NULL, NULL};
3728  LDAPMod   *mods[20];
3729  int n;
3730  int i;
3731
3732  mail_v[0] = NULL;
3733
3734  n = 0;
3735  ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
3736  ADD_ATTR("mailNickName", mail_v, LDAP_MOD_REPLACE);
3737  ADD_ATTR("proxyAddresses", mail_v, LDAP_MOD_REPLACE);
3738  ADD_ATTR("targetAddress", mail_v, LDAP_MOD_REPLACE);
3739  mods[n] = NULL;
3740
3741  gPtr = (*linklist_base);
3742 
3743  while(gPtr) {
3744    rc = ldap_modify_s(ld, gPtr->dn, mods);
3745   
3746    if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
3747      {
3748        com_err(whoami, 0, "Unable to modify contact %s in directory : %s",
3749                gPtr->dn, ldap_err2string(rc));
3750        return(rc);
3751      }
3752
3753    gPtr = gPtr->next;
3754  }
3755
3756  for (i = 0; i < n; i++)
3757    free(mods[i]);
3758 
3759    return(rc);
3760}
3761
3762int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou)
3763{
3764  LDAPMod *mods[20];
3765  LK_ENTRY  *group_base;
3766  int  group_count;
3767  char new_dn[256];
3768  char cn_user_name[256];
3769  char contact_name[256];
3770  char mail_nickname[256];
3771  char proxy_address_internal[256];
3772  char proxy_address_external[256];
3773  char target_address[256];
3774  char internal_contact_name[256];
3775  char filter[128];
3776  char mail[256];
3777  char principal[256];
3778  char mit_address_book[256];
3779  char default_address_book[256];
3780  char contact_address_book[256];
3781  char uid[256];
3782  char *email_v[] = {NULL, NULL};
3783  char *cn_v[] = {NULL, NULL};
3784  char *contact_v[] = {NULL, NULL};
3785  char *uid_v[] = {NULL, NULL};
3786  char *mail_nickname_v[] = {NULL, NULL};
3787  char *proxy_address_internal_v[] = {NULL, NULL};
3788  char *proxy_address_external_v[] = {NULL, NULL};
3789  char *target_address_v[] = {NULL, NULL};
3790  char *mit_address_book_v[] = {NULL, NULL};
3791  char *default_address_book_v[] = {NULL, NULL};
3792  char *contact_address_book_v[] = {NULL, NULL};
3793  char *hide_address_lists_v[] = {NULL, NULL};
3794  char *attr_array[3];
3795  char *objectClass_v[] = {"top", "person",
3796                           "organizationalPerson",
3797                           "contact", NULL};
3798  char *objectClass_ldap_v[] = {"top", "person", "microsoftComTop",
3799                                "inetOrgPerson", "organizationalPerson",
3800                                "contact", "mailRecipient", "eduPerson",
3801                                NULL};
3802  char *name_v[] = {NULL, NULL};
3803  char *desc_v[] = {NULL, NULL};
3804  char *s;
3805  int  n;
3806  int  rc;
3807  int  i;
3808  char temp[256];
3809  char *c;
3810  char *mail_routing_v[] = {NULL, NULL};
3811  char *principal_v[] = {NULL, NULL};
3812
3813  if (!check_string(user))
3814    {
3815      com_err(whoami, 0, "Unable to process invalid LDAP name %s", user);
3816      return(AD_INVALID_NAME);
3817    }
3818
3819  strcpy(mail, user);
3820  strcpy(contact_name, mail);
3821  strcpy(internal_contact_name, mail);
3822 
3823  if((s = strchr(internal_contact_name, '@')) != NULL) {
3824    *s = '?';
3825  }
3826
3827  sprintf(cn_user_name,"CN=%s,%s,%s", escape_string(contact_name), group_ou,
3828          bind_path);
3829
3830  sprintf(target_address, "SMTP:%s", contact_name);
3831  sprintf(proxy_address_external, "SMTP:%s", contact_name);
3832  sprintf(mail_nickname, "%s", internal_contact_name);
3833 
3834  cn_v[0] = cn_user_name;
3835  contact_v[0] = contact_name;
3836  uid_v[0] = uid;
3837  name_v[0] = user;
3838  desc_v[0] = "Auto account created by Moira";
3839  email_v[0] = mail;
3840  proxy_address_internal_v[0] = proxy_address_internal;
3841  proxy_address_external_v[0] = proxy_address_external;
3842  mail_nickname_v[0] = mail_nickname;
3843  target_address_v[0] = target_address;
3844  mit_address_book_v[0] = mit_address_book;
3845  default_address_book_v[0] = default_address_book;
3846  contact_address_book_v[0] = contact_address_book;
3847  strcpy(new_dn, cn_user_name);
3848  n = 0;
3849
3850  ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
3851
3852  if(!ActiveDirectory)
3853    {
3854      if(!strcmp(group_ou, contact_ou))
3855        sprintf(uid, "%s%s", contact_name, "_strings");
3856     
3857      if(!strcmp(group_ou, kerberos_ou))
3858        sprintf(uid, "%s%s", contact_name, "_kerberos");
3859
3860      uid_v[0] = uid;
3861
3862      ADD_ATTR("sn", contact_v, LDAP_MOD_ADD);
3863      ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
3864    }
3865
3866  if(ActiveDirectory)
3867    {
3868      ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
3869    }
3870  else
3871    {
3872      ADD_ATTR("objectClass", objectClass_ldap_v, LDAP_MOD_ADD);
3873    }
3874
3875  ADD_ATTR("name", name_v, LDAP_MOD_ADD);
3876  ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
3877  ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
3878
3879  if (Exchange)
3880    {
3881      if((s = strstr(mail, "@mit.edu")) != (char *) NULL)
3882        return(rc);
3883
3884      if (!strcmp(group_ou, contact_ou) && email_isvalid(mail))
3885        {
3886          group_count = 0;
3887          group_base = NULL;
3888         
3889          sprintf(filter, "(&(objectClass=user)(homeMDB=*)(cn=%s))", mail);
3890          attr_array[0] = "cn";
3891          attr_array[1] = NULL;
3892
3893          if ((rc = linklist_build(ld, bind_path, filter, attr_array,
3894                                   &group_base, &group_count,
3895                                   LDAP_SCOPE_SUBTREE)) != 0)
3896            {
3897              com_err(whoami, 0, "Unable to process contact %s : %s",
3898                      user, ldap_err2string(rc));
3899              return(rc);
3900            }
3901     
3902          if (group_count)
3903            {
3904              com_err(whoami, 0, "Object already exists with name %s",
3905                      user);
3906              return(1);
3907            }
3908
3909          linklist_free(group_base);
3910          group_base = NULL;
3911          group_count = 0;
3912     
3913          sprintf(filter, "(&(objectClass=group)(cn=%s))", mail);
3914          attr_array[0] = "cn";
3915          attr_array[1] = NULL;
3916
3917          if ((rc = linklist_build(ld, bind_path, filter, attr_array,
3918                                   &group_base, &group_count,
3919                                   LDAP_SCOPE_SUBTREE)) != 0)
3920            {
3921              com_err(whoami, 0, "Unable to process contact %s : %s",
3922                      user, ldap_err2string(rc));
3923              return(rc);
3924            }
3925         
3926          if (group_count)
3927            {
3928              com_err(whoami, 0, "Object already exists with name %s",
3929                      user);
3930              return(1);
3931            }
3932 
3933          linklist_free(group_base);
3934          group_count = 0;
3935          group_base = NULL;
3936
3937          sprintf(filter, "(&(objectClass=user)(homeMDB=*)(mail=%s))", mail);
3938          attr_array[0] = "cn";
3939          attr_array[1] = NULL;
3940
3941          if ((rc = linklist_build(ld, bind_path, filter, attr_array,
3942                                   &group_base, &group_count,
3943                                   LDAP_SCOPE_SUBTREE)) != 0)
3944            {
3945              com_err(whoami, 0, "Unable to process contact %s : %s",
3946                      user, ldap_err2string(rc));
3947              return(rc);
3948            }
3949         
3950          if (group_count)
3951            {
3952              com_err(whoami, 0, "Object already exists with name %s",
3953                      user);
3954              return(1);
3955            }
3956       
3957          linklist_free(group_base);
3958          group_base = NULL;
3959          group_count = 0;
3960
3961          sprintf(filter, "(&(objectClass=group)(mail=%s))", mail);
3962          attr_array[0] = "cn";
3963          attr_array[1] = NULL;
3964
3965          if ((rc = linklist_build(ld, bind_path, filter, attr_array,
3966                                   &group_base, &group_count,
3967                                   LDAP_SCOPE_SUBTREE)) != 0)
3968            {
3969              com_err(whoami, 0, "Unable to process contact %s : %s",
3970                      user, ldap_err2string(rc));
3971              return(rc);
3972            }
3973     
3974          if (group_count)
3975            {
3976              com_err(whoami, 0, "Object already exists with name %s",
3977                      user);
3978              return(1);
3979            }
3980         
3981          linklist_free(group_base);
3982          group_base = NULL;
3983          group_count = 0;
3984
3985          sprintf(filter,
3986                  "(&(objectClass=user)(homeMDB=*)(proxyAddresses=smtp:%s))",
3987                  mail);
3988          attr_array[0] = "cn";
3989          attr_array[1] = NULL;
3990
3991          if ((rc = linklist_build(ld, bind_path, filter, attr_array,
3992                                   &group_base, &group_count,
3993                                   LDAP_SCOPE_SUBTREE)) != 0)
3994            {
3995              com_err(whoami, 0, "Unable to process contact %s : %s",
3996                      user, ldap_err2string(rc));
3997              return(rc);
3998            }
3999     
4000          if (group_count)
4001            {
4002              com_err(whoami, 0, "Object already exists with name %s",
4003                      user);
4004              return(1);
4005            }
4006
4007          linklist_free(group_base);
4008          group_base = NULL;
4009          group_count = 0;
4010
4011          sprintf(filter, "(&(objectClass=group)(proxyAddresses=smtp:%s))",
4012                  mail);
4013          attr_array[0] = "cn";
4014          attr_array[1] = NULL;
4015
4016          if ((rc = linklist_build(ld, bind_path, filter, attr_array,
4017                                   &group_base, &group_count,
4018                                   LDAP_SCOPE_SUBTREE)) != 0)
4019            {
4020              com_err(whoami, 0, "Unable to process contact %s : %s",
4021                      user, ldap_err2string(rc));
4022              return(rc);
4023            }
4024     
4025          if (group_count)
4026            {
4027              com_err(whoami, 0, "Object already exists with name %s",
4028                      user);
4029              return(1);
4030            }
4031
4032          ADD_ATTR("mail", email_v, LDAP_MOD_ADD);
4033          ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_ADD);
4034          ADD_ATTR("proxyAddresses", proxy_address_external_v, LDAP_MOD_ADD);
4035          ADD_ATTR("targetAddress", target_address_v, LDAP_MOD_ADD);
4036         
4037          hide_address_lists_v[0] = "TRUE";
4038          ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4039                   LDAP_MOD_ADD);
4040        }
4041    }
4042
4043  if(!ActiveDirectory)
4044    {
4045      if((c = strchr(mail, '@')) == NULL)
4046          sprintf(temp, "%s@mit.edu", mail);
4047      else
4048          sprintf(temp, "%s", mail);
4049
4050      mail_routing_v[0] = temp;
4051      email_v[0] = temp;
4052      principal_v[0] = principal;
4053
4054      if(!strcmp(group_ou, contact_ou))
4055        {
4056          ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
4057          ADD_ATTR("eduPersonPrincipalName", mail_routing_v, LDAP_MOD_ADD);
4058        }
4059    }
4060
4061  mods[n] = NULL;
4062
4063  rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
4064
4065  for (i = 0; i < n; i++)
4066    free(mods[i]);
4067 
4068  if (Exchange)
4069    {
4070      if ((rc != LDAP_SUCCESS) && (rc == LDAP_ALREADY_EXISTS) &&
4071          !strcmp(group_ou, contact_ou) && email_isvalid(mail))
4072        {
4073          n = 0;
4074         
4075          ADD_ATTR("mail", email_v, LDAP_MOD_REPLACE);
4076          ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
4077          ADD_ATTR("proxyAddresses", proxy_address_external_v,
4078                   LDAP_MOD_REPLACE);
4079          ADD_ATTR("targetAddress", target_address_v, LDAP_MOD_REPLACE);
4080
4081          hide_address_lists_v[0] = "TRUE";
4082          ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4083                   LDAP_MOD_REPLACE);
4084   
4085          mods[n] = NULL;
4086          rc = ldap_modify_s(ld, new_dn, mods);
4087     
4088          if (rc)
4089            {
4090              com_err(whoami, 0, "Unable to update contact %s", mail);
4091            }
4092     
4093          for (i = 0; i < n; i++)
4094            free(mods[i]);
4095        }
4096    }
4097
4098  if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
4099    {
4100      com_err(whoami, 0, "Unable to create contact %s : %s",
4101              user, ldap_err2string(rc));
4102      return(rc);
4103    }
4104
4105  return(0);
4106}
4107
4108int user_update(LDAP *ldap_handle, char *dn_path, char *user_name,
4109                char *Uid, char *MitId, char *MoiraId, int State,
4110                char *WinHomeDir, char *WinProfileDir, char *first,
4111                char *middle, char *last, char *shell, char *class)
4112{
4113  LDAPMod   *mods[40];
4114  LK_ENTRY  *group_base;
4115  int  group_count;
4116  char distinguished_name[512];
4117  char displayName[256];
4118  char address_book[1024];
4119  char *mitMoiraId_v[] = {NULL, NULL};
4120  char *mitMoiraClass_v[] = {NULL, NULL};
4121  char *mitMoiraStatus_v[] = {NULL, NULL};
4122  char *uid_v[] = {NULL, NULL};
4123  char *mitid_v[] = {NULL, NULL};
4124  char *homedir_v[] = {NULL, NULL};
4125  char *apple_homedir_v[] = {NULL, NULL};
4126  char *winProfile_v[] = {NULL, NULL};
4127  char *drives_v[] = {NULL, NULL};
4128  char *userAccountControl_v[] = {NULL, NULL};
4129  char *alt_recipient_v[] = {NULL, NULL};
4130  char *hide_address_lists_v[] = {NULL, NULL};
4131  char *mail_v[] = {NULL, NULL};
4132  char *gid_v[] = {NULL, NULL};
4133  char *loginshell_v[] = {NULL, NULL};
4134  char *principal_v[] = {NULL, NULL};
4135  char *address_book_v[] = {NULL, NULL, NULL, NULL, NULL};
4136  char userAccountControlStr[80];
4137  int  n;
4138  int  rc;
4139  int  i;
4140  int  OldUseSFU30;
4141  u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD |
4142    UF_PASSWD_CANT_CHANGE;
4143  char filter[128];
4144  char *attr_array[3];
4145  char temp[1024];
4146  char mail[256];
4147  char filesys_name[256];
4148  char contact_mail[256];
4149  char filter_exp[1024];
4150  char search_path[512];
4151  char TemplateDn[512];
4152  char TemplateSamName[128];
4153  char alt_recipient[256];
4154  char principal[256];
4155  char status[256];
4156  char acBERBuf[N_SD_BER_BYTES];
4157  LDAPControl sControl = {"1.2.840.113556.1.4.801",
4158                          { N_SD_BER_BYTES, acBERBuf },
4159                          TRUE};
4160  LDAPControl *apsServerControls[] = {&sControl, NULL};
4161  LDAPMessage *psMsg;
4162  LDAP_BERVAL   **ppsValues;
4163  ULONG dwInfo;
4164  char *argv[3];
4165  char *homeMDB;
4166  char *homeServerName;
4167  char *save_argv[7];
4168  char search_string[256];
4169  char *p, *q;
4170  char *mail_routing_v[] = {NULL, NULL};
4171  char *mail_alternate_v[] = {NULL, NULL};
4172  char *mit_moira_imap_address_v[] = {NULL, NULL};
4173  char *deliver_and_redirect_v[] = {NULL, NULL};
4174  char *c;
4175
4176  dwInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
4177    DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
4178  BEREncodeSecurityBits(dwInfo, acBERBuf);
4179
4180  if (!check_string(user_name))
4181    {
4182      com_err(whoami, 0, "Unable to process invalid LDAP user name %s",
4183              user_name);
4184      return(AD_INVALID_NAME);
4185    }
4186 
4187  memset(contact_mail, '\0', sizeof(contact_mail));
4188  if(Exchange)
4189    sprintf(contact_mail, "%s@exchange-forwarding.mit.edu", user_name);
4190  else
4191    sprintf(contact_mail, "%s@mit.edu", user_name);   
4192  memset(mail, '\0', sizeof(mail));
4193  sprintf(mail, "%s@%s", user_name, lowercase(ldap_domain));
4194  memset(alt_recipient, '\0', sizeof(alt_recipient));
4195  sprintf(alt_recipient, "cn=%s@exchange-forwarding.mit.edu,%s,%s", user_name,
4196          contact_ou, dn_path);
4197  sprintf(search_string, "@%s", uppercase(ldap_domain));
4198  memset(filesys_name, '\0', sizeof(filesys_name));
4199  sprintf(filesys_name, "%s.po", user_name);
4200
4201  if (Exchange)
4202    {
4203      if(contact_create(ldap_handle, dn_path, contact_mail, contact_ou))
4204        {
4205          com_err(whoami, 0, "Unable to create user contact %s", contact_mail);
4206        }
4207    }
4208
4209  group_count = 0;
4210  group_base = NULL;
4211
4212  memset(displayName, '\0', sizeof(displayName));
4213
4214  if (strlen(MoiraId) != 0)
4215    {
4216      if(ActiveDirectory)
4217        {
4218          sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
4219        }
4220      else
4221        {
4222          sprintf(filter,
4223                  "(&(objectClass=mitPerson)(mitMoiraId=%s))", MoiraId);
4224        }
4225
4226      attr_array[0] = "cn";
4227      attr_array[1] = NULL;
4228      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
4229                               &group_base, &group_count,
4230                               LDAP_SCOPE_SUBTREE)) != 0)
4231        {
4232          com_err(whoami, 0, "Unable to process user %s : %s",
4233                  user_name, ldap_err2string(rc));
4234          return(rc);
4235        }
4236    }
4237
4238  if (group_count != 1)
4239    {
4240      linklist_free(group_base);
4241      group_base = NULL;
4242      group_count = 0;
4243      sprintf(filter, "(sAMAccountName=%s)", user_name);
4244      attr_array[0] = "cn";
4245      attr_array[1] = NULL;
4246      sprintf(temp, "%s,%s", user_ou, dn_path);
4247      if ((rc = linklist_build(ldap_handle, temp, filter, attr_array,
4248                               &group_base, &group_count,
4249                               LDAP_SCOPE_SUBTREE)) != 0)
4250        {
4251          com_err(whoami, 0, "Unable to process user %s : %s",
4252                  user_name, ldap_err2string(rc));
4253          return(rc);
4254        }
4255    }
4256
4257  if (group_count != 1)
4258    {
4259      com_err(whoami, 0, "Unable to find user %s in directory",
4260              user_name);
4261      linklist_free(group_base);
4262      return(AD_NO_USER_FOUND);
4263    }
4264
4265  strcpy(distinguished_name, group_base->dn);
4266
4267  linklist_free(group_base);
4268  group_count = 0;
4269
4270  if(!ActiveDirectory)
4271    {
4272      if (rc = moira_connect())
4273        {
4274          critical_alert(whoami, "Ldap incremental",
4275                         "Error contacting Moira server : %s",
4276                         error_message(rc));
4277          return;
4278        }
4279 
4280      argv[0] = filesys_name;
4281
4282      if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info,
4283                          save_argv)))
4284        {
4285          n = 0;
4286          ADD_ATTR("mitMoiraIMAPAddress", mit_moira_imap_address_v,
4287                   LDAP_MOD_REPLACE);
4288          mods[n] = NULL;
4289          rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4290         
4291          if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
4292            rc = LDAP_SUCCESS;
4293
4294          if(rc)
4295            com_err(whoami, 0,
4296                    "Unable to set the mitMoiraIMAPAddress for %s : %s",
4297                    user_name, ldap_err2string(rc));
4298
4299          sprintf(temp, "%s@%s", user_name, save_argv[FS_MACHINE]);
4300         
4301          mit_moira_imap_address_v[0]  = temp;
4302               
4303          n = 0;
4304          ADD_ATTR("mitMoiraIMAPAddress", mit_moira_imap_address_v,
4305                   LDAP_MOD_ADD);
4306          mods[n] = NULL;
4307          rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4308         
4309          if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
4310            rc = LDAP_SUCCESS;
4311         
4312          if(rc)
4313            com_err(whoami, 0, "Unable to set the mitMoiraIMAPAddress for "
4314                    "%s : %s", user_name, ldap_err2string(rc));   
4315        } else if(rc==MR_NO_MATCH) {
4316         
4317          n = 0;
4318          ADD_ATTR("mitMoiraIMAPServer", mit_moira_imap_address_v,
4319                   LDAP_MOD_REPLACE);
4320          mods[n] = NULL;
4321          rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4322         
4323          if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
4324            rc = LDAP_SUCCESS;
4325
4326          if(rc)
4327            com_err(whoami, 0,
4328                    "Unable to set the mitMoiraIMAPAddress for %s : %s",
4329                    user_name, ldap_err2string(rc));
4330
4331        }
4332   
4333      argv[0] = user_name;
4334         
4335      if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
4336        {
4337          n = 0;
4338          ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_REPLACE);
4339          mods[n] = NULL;
4340          rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4341         
4342          if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
4343            rc = LDAP_SUCCESS;
4344
4345          if(rc)
4346            com_err(whoami, 0,
4347                    "Unable to set the mailRoutingAddress for %s : %s",
4348                    user_name, ldap_err2string(rc));
4349         
4350          p = strdup(save_argv[3]);
4351         
4352          if((c = strchr(p, ',')) != NULL)
4353            {
4354              q = strtok(p, ",");
4355              StringTrim(q);
4356
4357              if ((c = strchr(q, '@')) == NULL)
4358                sprintf(temp, "%s@mit.edu", q);
4359              else
4360                sprintf(temp, "%s", q);
4361             
4362              if(email_isvalid(temp) && State != US_DELETED)
4363                {
4364                  mail_routing_v[0]  = temp;
4365                 
4366                  n = 0;
4367                  ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
4368                  mods[n] = NULL;
4369                  rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4370
4371                  if (rc == LDAP_ALREADY_EXISTS ||
4372                      rc == LDAP_TYPE_OR_VALUE_EXISTS)
4373                    rc = LDAP_SUCCESS;
4374   
4375                  if(rc)
4376                    com_err(whoami, 0,
4377                            "Unable to set the mailRoutingAddress for %s : %s",
4378                            user_name, ldap_err2string(rc));
4379                }
4380
4381              while((q = strtok(NULL, ",")) != NULL) {
4382                StringTrim(q);
4383               
4384                if((c = strchr(q, '@')) == NULL)
4385                  sprintf(temp, "%s@mit.edu", q);
4386                else
4387                  sprintf(temp, "%s", q);
4388
4389                if(email_isvalid(temp) && State != US_DELETED)
4390                  {
4391                    mail_routing_v[0]  = temp;
4392               
4393                    n = 0;
4394                    ADD_ATTR("mailRoutingAddress", mail_routing_v,
4395                             LDAP_MOD_ADD);
4396                    mods[n] = NULL;
4397                    rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4398                   
4399                    if (rc == LDAP_ALREADY_EXISTS ||
4400                        rc == LDAP_TYPE_OR_VALUE_EXISTS)
4401                      rc = LDAP_SUCCESS;
4402                   
4403                    if(rc)
4404                      com_err(whoami, 0,
4405                              "Unable to set the mailRoutingAddress for "
4406                              "%s : %s",
4407                              user_name, ldap_err2string(rc));
4408                  }
4409              }
4410            } else {
4411              StringTrim(p);
4412
4413            if((c = strchr(p, '@')) == NULL)
4414              sprintf(temp, "%s@mit.edu", p);
4415            else
4416              sprintf(temp, "%s", p);
4417           
4418            if(email_isvalid(temp) && State != US_DELETED)
4419              {
4420                mail_routing_v[0]  = temp;
4421               
4422                n = 0;
4423                ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
4424                mods[n] = NULL;
4425                rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4426               
4427                if (rc == LDAP_ALREADY_EXISTS ||
4428                    rc == LDAP_TYPE_OR_VALUE_EXISTS)
4429                  rc = LDAP_SUCCESS;
4430               
4431                if(rc)
4432                  com_err(whoami, 0,
4433                          "Unable to set the mailRoutingAddress for %s : %s",
4434                          user_name, ldap_err2string(rc));
4435              }
4436            }
4437        } else if(rc==MR_NO_MATCH) {
4438         
4439          n = 0;
4440          ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_REPLACE);
4441          mods[n] = NULL;
4442          rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4443         
4444          if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
4445            rc = LDAP_SUCCESS;
4446
4447          if(rc)
4448            com_err(whoami, 0,
4449                    "Unable to set the mailRoutingAddress for %s : %s",
4450                    user_name, ldap_err2string(rc));
4451        }
4452      moira_disconnect();
4453    }
4454
4455  if ((strlen(MitId) != 0) && (MitId[0] == '9'))
4456    rc = attribute_update(ldap_handle, distinguished_name, MitId,
4457                          "employeeID", user_name);
4458  else
4459    rc = attribute_update(ldap_handle, distinguished_name, "none",
4460                          "employeeID", user_name);
4461
4462  if(strlen(first)) {
4463    strcat(displayName, first);
4464  }
4465
4466  if(strlen(middle)) {
4467    if(strlen(first))
4468      strcat(displayName, " ");
4469
4470    strcat(displayName, middle);
4471  }
4472
4473  if(strlen(last)) {
4474    if(strlen(middle) || strlen(first))
4475      strcat(displayName, " ");
4476
4477    strcat(displayName, last);
4478  }
4479
4480  if(strlen(displayName))
4481    rc = attribute_update(ldap_handle, distinguished_name, displayName,
4482                          "displayName", user_name);
4483  else
4484    rc = attribute_update(ldap_handle, distinguished_name, user_name,
4485                          "displayName", user_name);
4486
4487  if(!ActiveDirectory)
4488    {
4489      if(strlen(displayName))
4490        rc = attribute_update(ldap_handle, distinguished_name, displayName,
4491                              "cn", user_name);
4492      else
4493        rc = attribute_update(ldap_handle, distinguished_name, user_name,
4494                              "cn", user_name);
4495    }
4496
4497  if(!ActiveDirectory)
4498    {
4499      rc = attribute_update(ldap_handle, distinguished_name, displayName,
4500                            "eduPersonNickname", user_name);
4501    }
4502
4503  if(strlen(first))
4504    rc = attribute_update(ldap_handle, distinguished_name, first,
4505                          "givenName", user_name);
4506  else
4507    rc = attribute_update(ldap_handle, distinguished_name, "",
4508                          "givenName", user_name);
4509
4510  if(strlen(middle) == 1)
4511    rc = attribute_update(ldap_handle, distinguished_name, middle,
4512                          "initials", user_name);
4513  else
4514    rc = attribute_update(ldap_handle, distinguished_name, "",
4515                          "initials", user_name);
4516 
4517  if(strlen(last))
4518    rc = attribute_update(ldap_handle, distinguished_name, last,
4519                          "sn", user_name);
4520  else
4521    rc = attribute_update(ldap_handle, distinguished_name, "",
4522                          "sn", user_name);
4523
4524  if(ActiveDirectory)
4525    {
4526      rc = attribute_update(ldap_handle, distinguished_name, Uid, "uid",
4527                            user_name);
4528    }
4529  else
4530    {
4531      rc = attribute_update(ldap_handle, distinguished_name, user_name, "uid",
4532                            user_name);
4533    }
4534   
4535  rc = attribute_update(ldap_handle, distinguished_name, MoiraId,
4536                        "mitMoiraId", user_name);
4537
4538  n = 0;
4539  uid_v[0] = Uid;
4540
4541  if(ActiveDirectory)
4542    {
4543      if (!UseSFU30)
4544        {
4545          ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
4546        }
4547      else
4548        {
4549          ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_REPLACE);
4550        }
4551    }
4552  else
4553    {
4554      sprintf(principal, "%s@%s", user_name, PRIMARY_REALM);
4555      sprintf(status, "%d", State);
4556      principal_v[0] = principal;
4557      loginshell_v[0] = shell;
4558      mitMoiraClass_v[0] = class;
4559      mitMoiraStatus_v[0] = status;
4560      gid_v[0] = "101";
4561      ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
4562      ADD_ATTR("gidNumber", gid_v, LDAP_MOD_REPLACE);
4563      ADD_ATTR("loginShell", loginshell_v, LDAP_MOD_REPLACE);
4564      ADD_ATTR("eduPersonPrincipalName", mail_v, LDAP_MOD_REPLACE);
4565      ADD_ATTR("mitMoiraClass", mitMoiraClass_v, LDAP_MOD_REPLACE);
4566      ADD_ATTR("mitMoiraStatus", mitMoiraStatus_v, LDAP_MOD_REPLACE);
4567    }
4568
4569  if ((State != US_NO_PASSWD) && (State != US_REGISTERED))
4570    {
4571      userAccountControl |= UF_ACCOUNTDISABLE;
4572
4573      if (Exchange)
4574        {
4575          hide_address_lists_v[0] = "TRUE";
4576          ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4577                   LDAP_MOD_REPLACE);
4578        }
4579    }
4580  else
4581    {
4582      if (Exchange)
4583        {
4584          hide_address_lists_v[0] = NULL;
4585          address_book_v[0] = address_book;
4586          ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4587                   LDAP_MOD_REPLACE);
4588
4589          /*
4590          sprintf(address_book, "%s%s", GLOBAL_ADDRESS_LIST_PREFIX, dn_path);
4591          address_book_v[0] = strdup(address_book);
4592          memset(address_book, '\0', sizeof(address_book));
4593          sprintf(address_book, "%s%s", ADDRESS_LIST_PREFIX, dn_path);
4594          address_book_v[1] = strdup(address_book);
4595          memset(address_book, '\0', sizeof(address_book));
4596          sprintf(address_book, "%s%s", EMAIL_ADDRESS_LIST_PREFIX, dn_path);
4597          address_book_v[2] = strdup(address_book);
4598          memset(address_book, '\0', sizeof(address_book));
4599          sprintf(address_book, "%s%s", ALL_ADDRESS_LIST_PREFIX, dn_path);
4600          address_book_v[3] = strdup(address_book);
4601          memset(address_book, '\0', sizeof(address_book));
4602         
4603          ADD_ATTR("showInAddressBook", address_book_v,
4604                   LDAP_MOD_REPLACE);
4605          */
4606        }
4607    }
4608
4609  sprintf(userAccountControlStr, "%ld", userAccountControl);
4610  userAccountControl_v[0] = userAccountControlStr;
4611  ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_REPLACE);
4612
4613  if (Exchange)
4614    {
4615      if (rc = moira_connect())
4616        {
4617          critical_alert(whoami, "Ldap incremental",
4618                         "Error contacting Moira server : %s",
4619                         error_message(rc));
4620          return;
4621        }
4622 
4623      argv[0] = user_name;
4624
4625      if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
4626        {
4627          if(!strcmp(save_argv[1], "EXCHANGE") ||
4628             (strstr(save_argv[3], search_string) != NULL))
4629            {
4630              alt_recipient_v[0] = NULL;
4631              ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_REPLACE);
4632
4633              argv[0] = exchange_acl;
4634              argv[1] = "USER";
4635              argv[2] = user_name;
4636             
4637              rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
4638             
4639              if ((rc) && (rc != MR_EXISTS))
4640                {
4641                  com_err(whoami, 0, "Unable to add user %s to %s: %s",
4642                          user_name, exchange_acl, error_message(rc));
4643                }
4644
4645              if(!strcmp(save_argv[1], "SPLIT") ||
4646                 !strcmp(save_argv[1], "SMTP")) {
4647
4648                deliver_and_redirect_v[0] = "TRUE";
4649                alt_recipient_v[0] = alt_recipient;
4650                ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_REPLACE);
4651                ADD_ATTR("deliverAndRedirect", deliver_and_redirect_v,
4652                         LDAP_MOD_REPLACE);
4653              }
4654            }
4655          else
4656            {
4657              deliver_and_redirect_v[0] = "FALSE";
4658              alt_recipient_v[0] = alt_recipient;
4659              ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_REPLACE);
4660              ADD_ATTR("deliverAndRedirect", deliver_and_redirect_v,
4661                       LDAP_MOD_REPLACE);
4662             
4663              argv[0] = exchange_acl;
4664              argv[1] = "USER";
4665              argv[2] = user_name;
4666             
4667              rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
4668             
4669              if ((rc) && (rc != MR_NO_MATCH))
4670                { 
4671                  com_err(whoami, 0,
4672                          "Unable to remove user %s from %s: %s, %d",
4673                          user_name, exchange_acl, error_message(rc), rc);
4674                } 
4675            }
4676        }
4677      else
4678        {
4679          deliver_and_redirect_v[0] = "FALSE";
4680          alt_recipient_v[0] = alt_recipient;
4681          ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_REPLACE);
4682          ADD_ATTR("deliverAndRedirect", deliver_and_redirect_v,
4683                   LDAP_MOD_REPLACE);     
4684
4685          argv[0] = exchange_acl;
4686          argv[1] = "USER";
4687          argv[2] = user_name;
4688         
4689          rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
4690         
4691          if ((rc) && (rc != MR_NO_MATCH))
4692            { 
4693              com_err(whoami, 0,
4694                      "Unable to remove user %s from %s: %s, %d",
4695                      user_name, exchange_acl, error_message(rc), rc);
4696            } 
4697        }
4698     
4699      moira_disconnect();
4700    }
4701  else
4702    {
4703      mail_v[0] = contact_mail;
4704      ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
4705
4706      if(!ActiveDirectory)
4707        {
4708          ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_REPLACE);
4709        }
4710    }
4711
4712  n = SetHomeDirectory(ldap_handle, user_name, distinguished_name, WinHomeDir,
4713                       WinProfileDir, homedir_v, winProfile_v,
4714                       drives_v, apple_homedir_v, mods, LDAP_MOD_REPLACE, n);
4715
4716  if(ActiveDirectory)
4717    {
4718      sprintf(filter_exp, "(sAMAccountName=%s)", "UserTemplate.u");
4719      sprintf(search_path, "%s,%s", security_template_ou, dn_path);
4720      attr_array[0] = "sAMAccountName";
4721      attr_array[1] = NULL;
4722      group_count = 0;
4723      group_base = NULL;
4724   
4725      if ((rc = linklist_build(ldap_handle, search_path, filter_exp,
4726                               attr_array,
4727                               &group_base, &group_count,
4728                               LDAP_SCOPE_SUBTREE) != 0))
4729        return(1);
4730     
4731      if (group_count != 1)
4732        {
4733          com_err(whoami, 0, "Unable to process user security template: %s - "
4734                  "security not set", "UserTemplate.u");
4735          return(1);
4736        }
4737
4738      strcpy(TemplateDn, group_base->dn);
4739      strcpy(TemplateSamName, group_base->value);
4740      linklist_free(group_base);
4741      group_base = NULL;
4742      group_count = 0;
4743     
4744      rc = ldap_search_ext_s(ldap_handle, search_path, LDAP_SCOPE_SUBTREE,
4745                             filter_exp, NULL, 0, apsServerControls, NULL,
4746                             NULL, 0, &psMsg);
4747
4748      if ((psMsg = ldap_first_entry(ldap_handle, psMsg)) == NULL)
4749        {
4750          com_err(whoami, 0, "Unable to find user security template: %s - "
4751                  "security not set", "UserTemplate.u");
4752          return(1);
4753        }
4754     
4755      ppsValues = ldap_get_values_len(ldap_handle, psMsg,
4756                                      "ntSecurityDescriptor");
4757
4758      if (ppsValues == NULL)
4759        {
4760          com_err(whoami, 0, "Unable to find user security template: %s - "
4761                  "security not set", "UserTemplate.u");
4762          return(1);
4763        }
4764     
4765      ADD_ATTR("ntSecurityDescriptor", (char **)ppsValues,
4766               LDAP_MOD_REPLACE | LDAP_MOD_BVALUES);
4767    }
4768
4769  mods[n] = NULL;
4770
4771  if ((rc = ldap_modify_s(ldap_handle, distinguished_name,
4772                          mods)) != LDAP_SUCCESS)
4773    {
4774      OldUseSFU30 = UseSFU30;
4775      SwitchSFU(mods, &UseSFU30, n);
4776      if (OldUseSFU30 != UseSFU30)
4777        rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4778      if (rc)
4779        {
4780          com_err(whoami, 0, "Unable to modify user data for %s : %s",
4781                  user_name, ldap_err2string(rc));
4782        }
4783    }
4784 
4785  for (i = 0; i < n; i++)
4786    free(mods[i]);
4787
4788  return(rc);
4789}
4790
4791int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name,
4792                char *user_name)
4793{
4794  LDAPMod *mods[20];
4795  char new_dn[256];
4796  char old_dn[256];
4797  char upn[256];
4798  char mail[256];
4799  char contact_mail[256];
4800  char proxy_address[256];
4801  char proxy_address_mit[256];
4802  char proxy_address_x500[256];
4803  char query_base_dn[256];
4804  char temp[256];
4805  char *userPrincipalName_v[] = {NULL, NULL};
4806  char *altSecurityIdentities_v[] = {NULL, NULL};
4807  char *name_v[] = {NULL, NULL};
4808  char *samAccountName_v[] = {NULL, NULL};
4809  char *mail_v[] = {NULL, NULL};
4810  char *mail_nickname_v[] = {NULL, NULL};
4811  char *proxy_address_v[] = {NULL, NULL, NULL, NULL};
4812  char *query_base_dn_v[] = {NULL, NULL};
4813  char *principal_v[] = {NULL, NULL};
4814  char principal[256];
4815  int  n;
4816  int  rc;
4817  int  i;
4818
4819  if (!check_string(before_user_name))
4820    {
4821      com_err(whoami, 0,
4822              "Unable to process invalid LDAP user name %s", before_user_name);
4823      return(AD_INVALID_NAME);
4824    }
4825
4826  if (!check_string(user_name))
4827    {
4828      com_err(whoami, 0,
4829              "Unable to process invalid LDAP user name %s", user_name);
4830      return(AD_INVALID_NAME);
4831    }
4832
4833  strcpy(user_name, user_name);
4834 
4835  if(ActiveDirectory)
4836    sprintf(old_dn, "cn=%s,%s,%s", before_user_name, user_ou, dn_path);
4837  else
4838    sprintf(old_dn, "uid=%s,%s,%s", before_user_name, user_ou, dn_path);
4839
4840  if(ActiveDirectory)
4841    sprintf(new_dn, "cn=%s", user_name);
4842  else
4843    sprintf(new_dn, "uid=%s", user_name);
4844
4845  sprintf(mail, "%s@%s", user_name, lowercase(ldap_domain));
4846  if(Exchange)
4847    sprintf(contact_mail, "%s@exchange-forwarding.mit.edu", user_name);
4848  else
4849    sprintf(contact_mail, "%s@mit.edu", user_name);
4850  sprintf(proxy_address, "smtp:%s@%s", user_name, lowercase(ldap_domain));
4851  sprintf(proxy_address_mit, "SMTP:%s@mit.edu", user_name);
4852  sprintf(proxy_address_x500, "%s/cn=%s?mit.edu", X500_PREFIX, user_name);
4853 
4854  sprintf(principal, "%s@%s", user_name, PRIMARY_REALM);
4855
4856  if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, NULL, TRUE,
4857                           NULL, NULL)) != LDAP_SUCCESS)
4858    {
4859      com_err(whoami, 0, "Unable to rename user from %s to %s : %s",
4860              before_user_name, user_name, ldap_err2string(rc));
4861      return(rc);
4862    }
4863
4864  if (Exchange)
4865    {
4866      sprintf(temp, "cn=%s@exchange-forwarding.mit.edu,%s,%s", before_user_name,
4867              contact_ou, dn_path);
4868
4869      if(rc = ldap_delete_s(ldap_handle, temp))
4870        {
4871          com_err(whoami, 0, "Unable to delete user contact for %s",
4872                  user_name);
4873        }
4874     
4875      if(contact_create(ldap_handle, dn_path, contact_mail, contact_ou))
4876        {
4877          com_err(whoami, 0, "Unable to create user contact %s", contact_mail);
4878        }
4879    }
4880
4881  name_v[0] = user_name;
4882  sprintf(upn, "%s@%s", user_name, ldap_domain);
4883  userPrincipalName_v[0] = upn;
4884  principal_v[0] = principal;
4885  sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
4886  sprintf(query_base_dn, "%s%s", ADDRESS_LIST_PREFIX, dn_path);
4887  altSecurityIdentities_v[0] = temp;
4888  samAccountName_v[0] = user_name;
4889  mail_v[0] = mail;
4890  mail_nickname_v[0] = user_name;
4891  proxy_address_v[0] = proxy_address_mit;
4892  proxy_address_v[1] = proxy_address;
4893  query_base_dn_v[0] = query_base_dn;
4894
4895  n = 0;
4896  ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_REPLACE);
4897  ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_REPLACE);
4898  ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
4899  ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_REPLACE);
4900
4901  if(!ActiveDirectory)
4902    {
4903      ADD_ATTR("uid", samAccountName_v, LDAP_MOD_REPLACE);
4904      ADD_ATTR("eduPersonPrincipalName", mail_v, LDAP_MOD_REPLACE);
4905      ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
4906      ADD_ATTR("eduPersonNickname", name_v, LDAP_MOD_REPLACE);
4907    }
4908
4909  if (Exchange)
4910    {
4911      ADD_ATTR("msExchQueryBaseDN", query_base_dn_v, LDAP_MOD_REPLACE);
4912      ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
4913      ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
4914      ADD_ATTR("proxyAddresses", proxy_address_v, LDAP_MOD_REPLACE);
4915    }
4916  else
4917    {
4918      mail_v[0] = contact_mail;
4919      ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
4920
4921      if(!ActiveDirectory)
4922        {
4923          ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_REPLACE);
4924        }
4925    }
4926
4927  mods[n] = NULL;
4928 
4929  if(ActiveDirectory)
4930    sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, dn_path);
4931  else
4932    sprintf(new_dn, "uid=%s,%s,%s", user_name, user_ou, dn_path);
4933
4934  if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
4935    {
4936      com_err(whoami, 0,
4937              "Unable to modify user data for %s after renaming : %s",
4938              user_name, ldap_err2string(rc));
4939    }
4940 
4941  for (i = 0; i < n; i++)
4942    free(mods[i]);
4943
4944  return(rc);
4945}
4946
4947int user_create(int ac, char **av, void *ptr)
4948{
4949  LDAPMod *mods[40];
4950  char new_dn[256];
4951  char user_name[256];
4952  char sam_name[256];
4953  char upn[256];
4954  char mail[256];
4955  char contact_mail[256];
4956  char proxy_address[256];
4957  char mail_nickname[256];
4958  char query_base_dn[256];
4959  char displayName[256];
4960  char address_book[1024];
4961  char alt_recipient[256];
4962  char filesys_name[256];
4963  char *cn_v[] = {NULL, NULL};
4964  char *objectClass_v[] = {"top", "person", "organizationalPerson",
4965                           "user", NULL};
4966  char *objectClass_ldap_v[] = {"top",
4967                                "eduPerson", "posixAccount",
4968                                "apple-user", "shadowAccount",
4969                                "microsoftComTop", "securityPrincipal",
4970                                "inetOrgPerson", "user",
4971                                "organizationalPerson", "person",
4972                                "mailRecipient", NULL};
4973
4974  char *samAccountName_v[] = {NULL, NULL};
4975  char *altSecurityIdentities_v[] = {NULL, NULL};
4976  char *mitMoiraId_v[] = {NULL, NULL};
4977  char *mitMoiraClass_v[] = {NULL, NULL};
4978  char *mitMoiraStatus_v[] = {NULL, NULL};
4979  char *name_v[] = {NULL, NULL};
4980  char *desc_v[] = {NULL, NULL};
4981  char *userPrincipalName_v[] = {NULL, NULL};
4982  char *userAccountControl_v[] = {NULL, NULL};
4983  char *uid_v[] = {NULL, NULL};
4984  char *gid_v[] = {NULL, NULL};
4985  char *mitid_v[] = {NULL, NULL};
4986  char *homedir_v[] = {NULL, NULL};
4987  char *apple_homedir_v[] = {NULL, NULL};
4988  char *winProfile_v[] = {NULL, NULL};
4989  char *drives_v[] = {NULL, NULL};
4990  char *mail_v[] = {NULL, NULL};
4991  char *givenName_v[] = {NULL, NULL};
4992  char *sn_v[] = {NULL, NULL};
4993  char *initials_v[] = {NULL, NULL};
4994  char *displayName_v[] = {NULL, NULL};
4995  char *proxy_address_v[] = {NULL, NULL};
4996  char *mail_nickname_v[] = {NULL, NULL};
4997  char *query_base_dn_v[] = {NULL, NULL};
4998  char *address_book_v[] = {NULL, NULL, NULL, NULL, NULL};
4999  char *homeMDB_v[] = {NULL, NULL};
5000  char *homeServerName_v[] = {NULL, NULL};
5001  char *mdbUseDefaults_v[] = {NULL, NULL};
5002  char *mailbox_guid_v[] = {NULL, NULL};
5003  char *user_culture_v[] = {NULL, NULL};
5004  char *user_account_control_v[] = {NULL, NULL};
5005  char *msexch_version_v[] = {NULL, NULL};
5006  char *alt_recipient_v[] = {NULL, NULL};
5007  char *hide_address_lists_v[] = {NULL, NULL};
5008  char *principal_v[] = {NULL, NULL};
5009  char *loginshell_v[] = {NULL, NULL};
5010  char userAccountControlStr[80];
5011  char temp[1024];
5012  char principal[256];
5013  char filter_exp[1024];
5014  char search_path[512];
5015  char *attr_array[3];
5016  u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD |
5017    UF_PASSWD_CANT_CHANGE;
5018  int  n;
5019  int  rc;
5020  int  i;
5021  int  OldUseSFU30;
5022  char **call_args;
5023  char WinHomeDir[1024];
5024  char WinProfileDir[1024];
5025  char *homeMDB;
5026  char *homeServerName;
5027  ULONG dwInfo;
5028  char acBERBuf[N_SD_BER_BYTES];
5029  LK_ENTRY  *group_base;
5030  int    group_count;
5031  char TemplateDn[512];
5032  char TemplateSamName[128];
5033  LDAP_BERVAL **ppsValues;
5034  LDAPControl sControl = {"1.2.840.113556.1.4.801",
5035                          { N_SD_BER_BYTES, acBERBuf },
5036                          TRUE};
5037  LDAPControl *apsServerControls[] = {&sControl, NULL};
5038  LDAPMessage *psMsg;
5039  char *argv[3];
5040  char *save_argv[7];
5041  char search_string[256];
5042  char *o_v[] = {NULL, NULL};
5043  char *p, *q;
5044  char *mail_routing_v[] = {NULL, NULL};
5045  char *mail_alternate_v[] = {NULL, NULL};
5046  char *mit_moira_imap_address_v[] = {NULL, NULL};
5047  char *deliver_and_redirect_v[] = {NULL, NULL};
5048  char *c;
5049
5050  call_args = ptr;
5051
5052  dwInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
5053    DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
5054  BEREncodeSecurityBits(dwInfo, acBERBuf);
5055
5056  if (!check_string(av[U_NAME]))
5057    {
5058      callback_rc = AD_INVALID_NAME;
5059      com_err(whoami, 0, "Unable to process invalid LDAP user name %s",
5060              av[U_NAME]);
5061      return(AD_INVALID_NAME);
5062    }
5063
5064  memset(WinHomeDir, '\0', sizeof(WinHomeDir));
5065  memset(WinProfileDir, '\0', sizeof(WinProfileDir));
5066  memset(displayName, '\0', sizeof(displayName));
5067  memset(query_base_dn, '\0', sizeof(query_base_dn));
5068  memset(filesys_name, '\0', sizeof(filesys_name));
5069  strcpy(WinHomeDir, av[U_WINHOMEDIR]);
5070  strcpy(WinProfileDir, av[U_WINPROFILEDIR]);
5071  strcpy(user_name, av[U_NAME]);
5072  sprintf(upn, "%s@%s", user_name, ldap_domain);
5073  sprintf(sam_name, "%s", av[U_NAME]);
5074  sprintf(filesys_name, "%s.po", user_name);
5075
5076  if(strlen(av[U_FIRST])) {
5077    strcat(displayName, av[U_FIRST]);
5078  }
5079
5080  if(strlen(av[U_MIDDLE])) {
5081    if(strlen(av[U_FIRST]))
5082       strcat(displayName, " ");
5083 
5084    strcat(displayName, av[U_MIDDLE]);
5085  }
5086
5087  if(strlen(av[U_LAST])) {
5088    if(strlen(av[U_FIRST]) || strlen(av[U_MIDDLE]))
5089      strcat(displayName, " ");
5090
5091    strcat(displayName, av[U_LAST]);
5092  }
5093
5094  samAccountName_v[0] = sam_name;
5095
5096  if ((atoi(av[U_STATE]) != US_NO_PASSWD) &&
5097      (atoi(av[U_STATE]) != US_REGISTERED))
5098    {
5099      userAccountControl |= UF_ACCOUNTDISABLE;
5100    }
5101
5102  sprintf(userAccountControlStr, "%ld", userAccountControl);
5103  userAccountControl_v[0] = userAccountControlStr;
5104  userPrincipalName_v[0] = upn;
5105 
5106  if(ActiveDirectory)
5107    cn_v[0] = user_name;
5108  else
5109    cn_v[0] = displayName;
5110   
5111  name_v[0] = user_name;
5112  desc_v[0] = "Auto account created by Moira";
5113  mail_v[0] = mail;
5114  givenName_v[0] = av[U_FIRST];
5115
5116  if(ActiveDirectory)
5117    sn_v[0] = av[U_LAST];
5118  else
5119    if(strlen(av[U_LAST]))
5120      sn_v[0] = av[U_LAST];
5121    else
5122      sn_v[0] = av[U_NAME];
5123
5124  displayName_v[0] = displayName;
5125  mail_nickname_v[0] = user_name;
5126  o_v[0] = "Massachusetts Institute of Technology";
5127
5128  sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
5129  sprintf(principal, "%s@%s", user_name, PRIMARY_REALM);
5130  altSecurityIdentities_v[0] = temp;   
5131  principal_v[0] = principal;
5132
5133  if(ActiveDirectory)
5134    sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, call_args[1]);
5135  else
5136    sprintf(new_dn, "uid=%s,%s,%s", user_name, user_ou, call_args[1]);
5137
5138  sprintf(mail,"%s@%s", user_name, lowercase(ldap_domain));
5139  if(Exchange)
5140    sprintf(contact_mail, "%s@exchange-forwarding.mit.edu", user_name);
5141  else
5142    sprintf(contact_mail, "%s@mit.edu", user_name);   
5143  sprintf(query_base_dn, "%s%s", ADDRESS_LIST_PREFIX, call_args[1]);
5144  query_base_dn_v[0] = query_base_dn;
5145  sprintf(alt_recipient, "cn=%s@exchange-forwarding.mit.edu,%s,%s", user_name,
5146          contact_ou, call_args[1]);
5147  sprintf(search_string, "@%s", uppercase(ldap_domain));
5148
5149  if (Exchange)
5150    {
5151      if(contact_create((LDAP *)call_args[0], call_args[1], contact_mail,
5152                        contact_ou))
5153        {
5154          com_err(whoami, 0, "Unable to create user contact %s",
5155                  contact_mail);
5156        }
5157     
5158      if(find_homeMDB((LDAP *)call_args[0], call_args[1], &homeMDB,
5159                      &homeServerName))
5160        {
5161          com_err(whoami, 0, "Unable to locate homeMB and homeServerName");
5162          return(1);
5163        }
5164     
5165      com_err(whoami, 0, "homeMDB:%s", homeMDB);
5166      com_err(whoami, 0, "homeServerName:%s", homeServerName);
5167 
5168      homeMDB_v[0] = homeMDB;
5169      homeServerName_v[0] = homeServerName;
5170    }
5171
5172  n = 0;
5173
5174  ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
5175 
5176  if(ActiveDirectory)
5177    {
5178      ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
5179    }
5180  else
5181    {
5182      ADD_ATTR("objectClass", objectClass_ldap_v, LDAP_MOD_ADD);
5183    }
5184
5185  ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
5186  ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_ADD);
5187  ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_ADD);
5188  ADD_ATTR("name", name_v, LDAP_MOD_ADD);
5189  ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
5190
5191  if (Exchange)
5192    {
5193      if ((atoi(av[U_STATE]) != US_NO_PASSWD) &&
5194          (atoi(av[U_STATE]) != US_REGISTERED))
5195        {
5196          hide_address_lists_v[0] = "TRUE";
5197          ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
5198                   LDAP_MOD_ADD);
5199        }
5200      else
5201        {
5202          hide_address_lists_v[0] = "FALSE";
5203          ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
5204                   LDAP_MOD_ADD);
5205        }
5206
5207      ADD_ATTR("msExchQueryBaseDN", query_base_dn_v, LDAP_MOD_ADD);
5208      ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_ADD);
5209      ADD_ATTR("homeMDB", homeMDB_v, LDAP_MOD_ADD);
5210      mdbUseDefaults_v[0] = "TRUE";
5211      ADD_ATTR("mdbUseDefaults", mdbUseDefaults_v, LDAP_MOD_ADD);
5212      ADD_ATTR("msExchHomeServerName", homeServerName_v, LDAP_MOD_ADD);
5213     
5214      argv[0] = user_name;
5215   
5216      if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
5217        {
5218          if(!strcmp(save_argv[1], "EXCHANGE") ||
5219             (strstr(save_argv[3], search_string) != NULL))
5220            {
5221              argv[0] = exchange_acl;
5222              argv[1] = "USER";
5223              argv[2] = user_name;
5224             
5225              rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
5226             
5227              if ((rc) && (rc != MR_EXISTS))
5228                {
5229                  com_err(whoami, 0, "Unable to add user %s to %s: %s",
5230                          user_name, exchange_acl, error_message(rc));
5231                }
5232
5233              if(!strcmp(save_argv[1], "SPLIT") ||
5234                 !strcmp(save_argv[1], "SMTP")) {
5235               
5236                deliver_and_redirect_v[0] = "TRUE";
5237                alt_recipient_v[0] = alt_recipient;
5238
5239                ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_ADD);
5240                ADD_ATTR("deliverAndRedirect", deliver_and_redirect_v,
5241                         LDAP_MOD_ADD);
5242              }
5243            }
5244          else
5245            {
5246              alt_recipient_v[0] = alt_recipient;
5247              ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_ADD);
5248            }
5249        }
5250      else
5251        {
5252          alt_recipient_v[0] = alt_recipient;
5253          ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_ADD);
5254         
5255          com_err(whoami, 0, "Unable to fetch pobox for %s", user_name);
5256        }
5257    }
5258  else
5259    {
5260      mail_v[0] = contact_mail;
5261      ADD_ATTR("mail", mail_v, LDAP_MOD_ADD);
5262
5263      if(!ActiveDirectory)
5264        {
5265          ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_ADD);
5266        }
5267    }
5268
5269  if(strlen(av[U_FIRST])) {
5270    ADD_ATTR("givenName", givenName_v, LDAP_MOD_ADD);
5271  }
5272
5273  if(strlen(av[U_LAST]) || strlen(av[U_NAME])) {
5274    ADD_ATTR("sn", sn_v, LDAP_MOD_ADD);
5275  }
5276
5277  if(strlen(av[U_FIRST]) || strlen(av[U_MIDDLE]) || strlen(av[U_LAST])) {
5278    ADD_ATTR("displayName", displayName_v, LDAP_MOD_ADD);
5279
5280    if(!ActiveDirectory)
5281      {
5282        ADD_ATTR("eduPersonNickname", displayName_v, LDAP_MOD_ADD);     
5283      }
5284  } else {
5285    ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
5286
5287    if(!ActiveDirectory)
5288      {
5289        ADD_ATTR("eduPersonNickname", name_v, LDAP_MOD_ADD);           
5290      }
5291  }
5292
5293  if (strlen(av[U_MIDDLE]) == 1) {
5294    initials_v[0] = av[U_MIDDLE];
5295    ADD_ATTR("initials", initials_v, LDAP_MOD_ADD);
5296  }
5297
5298  if (strlen(call_args[2]) != 0)   
5299    {
5300      mitMoiraId_v[0] = call_args[2];
5301      ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
5302    }
5303
5304  ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_ADD);
5305
5306  if(!ActiveDirectory)
5307    {
5308      loginshell_v[0] = av[U_SHELL];
5309      mitMoiraClass_v[0] = av[U_CLASS];
5310      mitMoiraStatus_v[0] = av[U_STATE];
5311      ADD_ATTR("loginShell", loginshell_v, LDAP_MOD_ADD);
5312      ADD_ATTR("uid", samAccountName_v, LDAP_MOD_ADD);
5313      ADD_ATTR("eduPersonPrincipalName", mail_v, LDAP_MOD_ADD);
5314      ADD_ATTR("o", o_v, LDAP_MOD_ADD);
5315      ADD_ATTR("mitMoiraClass", mitMoiraClass_v, LDAP_MOD_ADD);
5316      ADD_ATTR("mitMoiraStatus", mitMoiraStatus_v, LDAP_MOD_ADD);
5317    }
5318
5319  if (strlen(av[U_UID]) != 0)
5320    {
5321      uid_v[0] = av[U_UID];
5322
5323      if(ActiveDirectory)
5324        {
5325          ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
5326        }
5327      else
5328        {
5329          gid_v[0] = "101";
5330          ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
5331          ADD_ATTR("gidNumber", gid_v, LDAP_MOD_ADD);
5332        }
5333
5334      if(ActiveDirectory)
5335        {
5336          if (!UseSFU30)
5337            {
5338              ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
5339            }
5340          else
5341            {
5342              ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_ADD);
5343            }
5344        }
5345    }
5346
5347  if ((strlen(av[U_MITID]) != 0) && (av[U_MITID][0] == '9'))
5348      mitid_v[0] = av[U_MITID];
5349  else
5350      mitid_v[0] = "none";
5351
5352  ADD_ATTR("employeeID", mitid_v, LDAP_MOD_ADD);
5353
5354  n = SetHomeDirectory((LDAP *)call_args[0], user_name, new_dn,
5355                       WinHomeDir, WinProfileDir, homedir_v, winProfile_v,
5356                       drives_v, apple_homedir_v, mods, LDAP_MOD_ADD, n);
5357 
5358  if(ActiveDirectory)
5359    {
5360      sprintf(filter_exp, "(sAMAccountName=%s)", "UserTemplate.u");
5361      sprintf(search_path, "%s,%s", security_template_ou, call_args[1]);
5362      attr_array[0] = "sAMAccountName";
5363      attr_array[1] = NULL;
5364      group_count = 0;
5365      group_base = NULL;
5366     
5367      if ((rc = linklist_build((LDAP *)call_args[0], search_path, filter_exp,
5368                               attr_array, &group_base, &group_count,
5369                               LDAP_SCOPE_SUBTREE) != 0))
5370        return(1);
5371     
5372      if (group_count != 1)
5373        {
5374          com_err(whoami, 0, "Unable to process user security template: %s - "
5375                  "security not set", "UserTemplate.u");
5376          return(1);
5377        }
5378     
5379      strcpy(TemplateDn, group_base->dn);
5380      strcpy(TemplateSamName, group_base->value);
5381      linklist_free(group_base);
5382      group_base = NULL;
5383      group_count = 0;
5384     
5385      rc = ldap_search_ext_s((LDAP *)call_args[0], search_path,
5386                             LDAP_SCOPE_SUBTREE, filter_exp, NULL, 0,
5387                             apsServerControls, NULL,
5388                             NULL, 0, &psMsg);
5389     
5390      if ((psMsg = ldap_first_entry((LDAP *)call_args[0], psMsg)) == NULL)
5391        {
5392          com_err(whoami, 0, "Unable to find user security template: %s - "
5393                  "security not set", "UserTemplate.u");
5394          return(1);
5395        }
5396     
5397      ppsValues = ldap_get_values_len((LDAP *)call_args[0], psMsg,
5398                                      "ntSecurityDescriptor");
5399      if (ppsValues == NULL)
5400        {
5401          com_err(whoami, 0, "Unable to find user security template: %s - "
5402                  "security not set", "UserTemplate.u");
5403          return(1);
5404        }
5405     
5406      ADD_ATTR("ntSecurityDescriptor", (char **)ppsValues,
5407               LDAP_MOD_REPLACE | LDAP_MOD_BVALUES);
5408    }
5409
5410  mods[n] = NULL;
5411
5412  rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
5413
5414  if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
5415    {
5416      OldUseSFU30 = UseSFU30;
5417      SwitchSFU(mods, &UseSFU30, n);
5418      if (OldUseSFU30 != UseSFU30)
5419        rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
5420    }
5421
5422  for (i = 0; i < n; i++)
5423    free(mods[i]);
5424
5425  if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
5426    {
5427      com_err(whoami, 0, "Unable to create user %s : %s",
5428              user_name, ldap_err2string(rc));
5429      callback_rc = rc;
5430      return(rc);
5431    }
5432
5433  if ((rc == LDAP_SUCCESS) && (SetPassword))
5434    {
5435      if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
5436        {
5437          ad_kdc_disconnect();
5438          if (!ad_server_connect(default_server, ldap_domain))
5439            {
5440              com_err(whoami, 0, "Unable to set password for user %s : %s",
5441                      user_name,
5442                      "cannot get changepw ticket from windows domain");
5443            }
5444          else
5445            {
5446              if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
5447                {
5448                  com_err(whoami, 0, "Unable to set password for user %s "
5449                          ": %ld", user_name, rc);
5450                }
5451            }
5452        }
5453    }
5454
5455  if(!ActiveDirectory)
5456    {
5457      if (rc = moira_connect())
5458        {
5459          critical_alert(whoami, "Ldap incremental",
5460                         "Error contacting Moira server : %s",
5461                         error_message(rc));
5462          return;
5463        }
5464 
5465      argv[0] = filesys_name;
5466
5467      if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info,
5468                          save_argv)))
5469        {
5470          n = 0;
5471          ADD_ATTR("mitMoiraIMAPAddress", mit_moira_imap_address_v,
5472                   LDAP_MOD_REPLACE);
5473          mods[n] = NULL;
5474          rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5475         
5476          if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
5477            rc = LDAP_SUCCESS;
5478
5479          if(rc)
5480            com_err(whoami, 0,
5481                    "Unable to set the mitMoiraIMAPAddress for %s : %s",
5482                    user_name, ldap_err2string(rc));
5483
5484          sprintf(temp, "%s@%s", user_name, save_argv[FS_MACHINE]);
5485         
5486          mit_moira_imap_address_v[0]  = temp;
5487               
5488          n = 0;
5489          ADD_ATTR("mitMoiraIMAPAddress", mit_moira_imap_address_v,
5490                   LDAP_MOD_ADD);
5491          mods[n] = NULL;
5492          rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5493         
5494          if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
5495            rc = LDAP_SUCCESS;
5496         
5497          if(rc)
5498            com_err(whoami, 0, "Unable to set the mitMoiraIMAPAddress for "
5499                    "%s : %s", user_name, ldap_err2string(rc));   
5500        } else if(rc==MR_NO_MATCH) {
5501         
5502          n = 0;
5503          ADD_ATTR("mitMoiraIMAPAddress", mit_moira_imap_address_v,
5504                   LDAP_MOD_REPLACE);
5505          mods[n] = NULL;
5506          rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5507         
5508          if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
5509            rc = LDAP_SUCCESS;
5510
5511          if(rc)
5512            com_err(whoami, 0,
5513                    "Unable to set the mitMoiraIMAPAddress for %s : %s",
5514                    user_name, ldap_err2string(rc));
5515
5516        }
5517
5518      argv[0] = user_name;
5519   
5520      if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
5521        {
5522          n = 0;
5523          ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_REPLACE);
5524          mods[n] = NULL;
5525          rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5526           
5527          if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
5528            rc = LDAP_SUCCESS;
5529
5530          if(rc)
5531            com_err(whoami, 0,
5532                    "Unable to set the mailRoutingAddress for %s : %s",
5533                    user_name, ldap_err2string(rc));
5534
5535          p = strdup(save_argv[3]);
5536         
5537          if((c = strchr(p, ',')) != NULL) {
5538            q = strtok(p, ",");
5539            StringTrim(q);
5540
5541            if ((c = strchr(q, '@')) == NULL)
5542              sprintf(temp, "%s@mit.edu", q);
5543            else
5544              sprintf(temp, "%s", q);
5545
5546            if(email_isvalid(temp) && atoi(av[U_STATE]) != US_DELETED)
5547              {
5548                mail_routing_v[0]  = temp;
5549
5550                n = 0;
5551                ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
5552                mods[n] = NULL;
5553                rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5554               
5555                if (rc == LDAP_ALREADY_EXISTS ||
5556                    rc == LDAP_TYPE_OR_VALUE_EXISTS)
5557                  rc = LDAP_SUCCESS;
5558               
5559                if(rc)
5560                  com_err(whoami, 0,
5561                          "Unable to set the mailRoutingAddress for %s : %s",
5562                          user_name, ldap_err2string(rc));
5563              }
5564
5565            while((q = strtok(NULL, ",")) != NULL) {
5566              StringTrim(q);
5567
5568              if((c = strchr(q, '@')) == NULL)
5569                sprintf(temp, "%s@mit.edu", q);
5570              else
5571                sprintf(temp, "%s", q);
5572
5573              if(email_isvalid(temp) && atoi(av[U_STATE]) != US_DELETED)
5574                {
5575                  mail_routing_v[0]  = temp;
5576                 
5577                  n = 0;
5578                  ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
5579                  mods[n] = NULL;
5580                  rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5581                 
5582                  if (rc == LDAP_ALREADY_EXISTS ||
5583                      rc == LDAP_TYPE_OR_VALUE_EXISTS)
5584                    rc = LDAP_SUCCESS;
5585                 
5586                  if(rc)
5587                    com_err(whoami, 0,
5588                            "Unable to set the mailRoutingAddress for %s : %s",
5589                            user_name, ldap_err2string(rc));
5590                }
5591            }
5592          } else {
5593            StringTrim(p);
5594
5595            if((c = strchr(p, '@')) == NULL)
5596              sprintf(temp, "%s@mit.edu", p);
5597            else
5598              sprintf(temp, "%s", p);
5599
5600            if(email_isvalid(temp) && atoi(av[U_STATE]) != US_DELETED)
5601              {
5602                mail_routing_v[0]  = temp;
5603               
5604                n = 0;
5605                ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
5606                mods[n] = NULL;
5607                rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5608               
5609                if (rc == LDAP_ALREADY_EXISTS ||
5610                    rc == LDAP_TYPE_OR_VALUE_EXISTS)
5611                  rc = LDAP_SUCCESS;
5612               
5613                if(rc)
5614                  com_err(whoami, 0,
5615                          "Unable to set the mailRoutingAddress for %s : %s",
5616                          user_name, ldap_err2string(rc));
5617              }
5618          }
5619        }
5620      moira_disconnect();
5621    }
5622
5623  return(0);
5624}
5625
5626int user_change_status(LDAP *ldap_handle, char *dn_path,
5627                       char *user_name, char *MoiraId,
5628                       int operation)
5629{
5630  char      filter[128];
5631  char      *attr_array[3];
5632  char      temp[256];
5633  char      distinguished_name[1024];
5634  char      **modvalues;
5635  char      *mitMoiraId_v[] = {NULL, NULL};
5636  LDAPMod   *mods[20];
5637  LK_ENTRY  *group_base;
5638  int       group_count;
5639  int       rc;
5640  int       i;
5641  int       n;
5642  ULONG     ulongValue;
5643
5644  if (!check_string(user_name))
5645    {
5646      com_err(whoami, 0, "Unable to process invalid LDAP user name %s",
5647              user_name);
5648      return(AD_INVALID_NAME);
5649    }
5650
5651  group_count = 0;
5652  group_base = NULL;
5653
5654  if (strlen(MoiraId) != 0)
5655    {
5656      sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
5657      attr_array[0] = "UserAccountControl";
5658      attr_array[1] = NULL;
5659      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
5660                               &group_base, &group_count,
5661                               LDAP_SCOPE_SUBTREE)) != 0)
5662        {
5663          com_err(whoami, 0, "Unable to process user %s : %s",
5664                  user_name, ldap_err2string(rc));
5665          return(rc);
5666        }
5667    }
5668
5669  if (group_count != 1)
5670    {
5671      linklist_free(group_base);
5672      group_count = 0;
5673      group_base = NULL;
5674      sprintf(filter, "(sAMAccountName=%s)", user_name);
5675      attr_array[0] = "UserAccountControl";
5676      attr_array[1] = NULL;
5677      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
5678                               &group_base, &group_count,
5679                               LDAP_SCOPE_SUBTREE)) != 0)
5680        {
5681          com_err(whoami, 0, "Unable to process user %s : %s",
5682                  user_name, ldap_err2string(rc));
5683          return(rc);
5684        }
5685    }
5686 
5687  if (group_count != 1)
5688    {
5689      linklist_free(group_base);
5690      com_err(whoami, 0, "Unable to find user %s in directory",
5691              user_name);
5692      return(LDAP_NO_SUCH_OBJECT);
5693    }
5694
5695  strcpy(distinguished_name, group_base->dn);
5696  ulongValue = atoi((*group_base).value);
5697
5698  if (operation == MEMBER_DEACTIVATE)
5699    ulongValue |= UF_ACCOUNTDISABLE;
5700  else   
5701    ulongValue &= ~UF_ACCOUNTDISABLE;
5702
5703  sprintf(temp, "%ld", ulongValue);
5704
5705  if ((rc = construct_newvalues(group_base, group_count, (*group_base).value,
5706                                temp, &modvalues, REPLACE)) == 1)
5707    goto cleanup;
5708
5709  linklist_free(group_base);
5710  group_base = NULL;
5711  group_count = 0;
5712  n = 0;
5713  ADD_ATTR("UserAccountControl", modvalues, LDAP_MOD_REPLACE);
5714
5715  if (strlen(MoiraId) != 0)
5716    {
5717    mitMoiraId_v[0] = MoiraId;
5718    ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
5719    }
5720
5721  mods[n] = NULL;
5722  rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
5723
5724  for (i = 0; i < n; i++)
5725    free(mods[i]);
5726
5727  free_values(modvalues);
5728
5729  if (rc != LDAP_SUCCESS)
5730    {
5731      com_err(whoami, 0, "Unable to change status of user %s : %s",
5732              user_name, ldap_err2string(rc));
5733    }
5734 
5735 cleanup:
5736  return(rc);
5737}
5738
5739int user_delete(LDAP *ldap_handle, char *dn_path,
5740                char *u_name, char *MoiraId)
5741{
5742  char      filter[128];
5743  char      *attr_array[3];
5744  char      distinguished_name[1024];
5745  char      user_name[512];
5746  LK_ENTRY  *group_base;
5747  int       group_count;
5748  int       rc;
5749  char      temp[256];
5750
5751  if (!check_string(u_name))
5752    return(AD_INVALID_NAME);
5753
5754  strcpy(user_name, u_name);
5755  group_count = 0;
5756  group_base = NULL;
5757
5758  if (strlen(MoiraId) != 0)
5759    {
5760      sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
5761      attr_array[0] = "name";
5762      attr_array[1] = NULL;
5763      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
5764                               &group_base, &group_count,
5765                               LDAP_SCOPE_SUBTREE)) != 0)
5766        {
5767          com_err(whoami, 0, "Unable to process user %s : %s",
5768                  user_name, ldap_err2string(rc));
5769          goto cleanup;
5770        }
5771    }
5772 
5773  if (group_count != 1)
5774    {
5775      linklist_free(group_base);
5776      group_count = 0;
5777      group_base = NULL;
5778      sprintf(filter, "(sAMAccountName=%s)", user_name);
5779      attr_array[0] = "name";
5780      attr_array[1] = NULL;
5781      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
5782                               &group_base, &group_count,
5783                               LDAP_SCOPE_SUBTREE)) != 0)
5784        {
5785          com_err(whoami, 0, "Unable to process user %s : %s",
5786                  user_name, ldap_err2string(rc));
5787          goto cleanup;
5788        }
5789    }
5790
5791  if (group_count != 1)
5792    {
5793      goto cleanup;
5794    }
5795 
5796  strcpy(distinguished_name, group_base->dn);
5797
5798  if (rc = ldap_delete_s(ldap_handle, distinguished_name))
5799    {
5800      com_err(whoami, 0, "Unable to process user %s : %s",
5801              user_name, ldap_err2string(rc));
5802    }
5803
5804  /* Need to add code to delete mit.edu contact */
5805
5806  if (Exchange)
5807    {
5808      sprintf(temp, "cn=%s@exchange-forwarding.mit.edu,%s,%s", user_name,
5809              contact_ou, dn_path);
5810
5811      if(rc = ldap_delete_s(ldap_handle, temp))
5812        {
5813          com_err(whoami, 0, "Unable to delete user contact for %s",
5814                  user_name);
5815        }
5816    }
5817
5818 cleanup:
5819  linklist_free(group_base);
5820
5821  return(0);
5822}
5823
5824void linklist_free(LK_ENTRY *linklist_base)
5825{
5826  LK_ENTRY *linklist_previous;
5827
5828  while (linklist_base != NULL)
5829    {
5830      if (linklist_base->dn != NULL)
5831        free(linklist_base->dn);
5832
5833      if (linklist_base->attribute != NULL)
5834        free(linklist_base->attribute);
5835
5836      if (linklist_base->value != NULL)
5837        free(linklist_base->value);
5838
5839      if (linklist_base->member != NULL)
5840        free(linklist_base->member);
5841
5842      if (linklist_base->type != NULL)
5843        free(linklist_base->type);
5844
5845      if (linklist_base->list != NULL)
5846        free(linklist_base->list);
5847
5848      linklist_previous = linklist_base;
5849      linklist_base = linklist_previous->next;
5850      free(linklist_previous);
5851    }
5852}
5853
5854void free_values(char **modvalues)
5855{
5856  int i;
5857
5858  i = 0;
5859
5860  if (modvalues != NULL)
5861    {
5862    while (modvalues[i] != NULL)
5863      {
5864        free(modvalues[i]);
5865        modvalues[i] = NULL;
5866        ++i;
5867      }
5868    free(modvalues);
5869  }
5870}
5871
5872static int illegalchars[] = {
5873  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
5874  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
5875  1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */
5876  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
5877  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
5878  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
5879  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
5880  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
5881  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5882  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5883  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5884  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5885  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5886  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5887  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5888  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5889};
5890
5891static int illegalchars_ldap[] = {
5892  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
5893  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
5894  0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* SPACE - / */
5895  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */
5896  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
5897  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, /* P - _ */
5898  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
5899  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
5900  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5901  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5902  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5903  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5904  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5905  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5906  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5907  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5908};
5909
5910int check_string(char *s)
5911{
5912  char  character;
5913  char  *string;
5914
5915  string = s;
5916
5917  for (; *s; s++)
5918    {
5919      character = *s;
5920
5921      if (isupper(character))
5922        character = tolower(character);
5923
5924      if(ActiveDirectory)
5925        {
5926          if (illegalchars[(unsigned) character])
5927            {
5928              com_err(whoami, 0, "Found illegal char '%c' (%d) in string %s",
5929                      character, (unsigned) character, string);
5930              return 0;
5931            }
5932        }
5933      else
5934        {
5935          if (illegalchars_ldap[(unsigned) character])
5936            {
5937              com_err(whoami, 0, "Found illegal char '%c' (%d) in string %s",
5938                      character, (unsigned) character, string);
5939              return 0;
5940            }
5941        }
5942    }
5943
5944  return(1);
5945}
5946
5947int check_container_name(char *s)
5948{
5949  char  character;
5950
5951  for (; *s; s++)
5952    {
5953      character = *s;
5954
5955      if (isupper(character))
5956        character = tolower(character);
5957
5958      if (character == ' ')
5959        continue;
5960
5961      if (illegalchars[(unsigned) character])
5962        return 0;
5963    }
5964
5965  return(1);
5966}
5967
5968int mr_connect_cl(char *server, char *client, int version, int auth)
5969{
5970  int   status;
5971  char  *motd;
5972  char  temp[128];
5973
5974  status = mr_connect(server);
5975
5976  if (status)
5977    {
5978      com_err(whoami, status, "while connecting to Moira");
5979      return status;
5980    }
5981
5982  status = mr_motd(&motd);
5983
5984  if (status)
5985    {
5986      mr_disconnect();
5987      com_err(whoami, status, "while checking server status");
5988      return status;
5989    }
5990
5991  if (motd)
5992    {
5993      sprintf(temp, "The Moira server is currently unavailable: %s", motd);
5994      com_err(whoami, status, temp);
5995      mr_disconnect();
5996      return status;
5997    }
5998
5999  status = mr_version(version);
6000
6001  if (status)
6002    {
6003      if (status == MR_UNKNOWN_PROC)
6004        {
6005          if (version > 2)
6006            status = MR_VERSION_HIGH;
6007          else
6008            status = MR_SUCCESS;
6009        }
6010
6011      if (status == MR_VERSION_HIGH)
6012        {
6013          com_err(whoami, 0, "Warning: This client is running newer code "
6014                  "than the server.");
6015                  com_err(whoami, 0, "Some operations may not work.");
6016        }
6017      else if (status && status != MR_VERSION_LOW)
6018        {
6019          com_err(whoami, status, "while setting query version number.");
6020          mr_disconnect();
6021          return status;
6022        }
6023    }
6024
6025  if (auth)
6026    {
6027      status = mr_krb5_auth(client);
6028      if (status)
6029        {
6030          com_err(whoami, status, "while authenticating to Moira.");
6031          mr_disconnect();
6032          return status;
6033        }
6034    }
6035 
6036  return MR_SUCCESS;
6037}
6038
6039void AfsToWinAfs(char* path, char* winPath)
6040{
6041  char* pathPtr;
6042  char* winPathPtr;
6043  strcpy(winPath, WINAFS);
6044  pathPtr = path + strlen(AFS);
6045  winPathPtr = winPath + strlen(WINAFS);
6046 
6047  while (*pathPtr)
6048    {
6049      if (*pathPtr == '/')
6050        *winPathPtr = '\\';
6051      else
6052        *winPathPtr = *pathPtr;
6053     
6054      pathPtr++;
6055      winPathPtr++;
6056    }
6057}
6058
6059int GetAceInfo(int ac, char **av, void *ptr)
6060{
6061  char **call_args;
6062  int   security_flag;
6063
6064  call_args = ptr;
6065 
6066  strcpy(call_args[0], av[L_ACE_TYPE]);
6067  strcpy(call_args[1], av[L_ACE_NAME]);
6068  security_flag = 0;
6069  get_group_membership(call_args[2], call_args[3], &security_flag, av);
6070  return(LDAP_SUCCESS); 
6071}
6072
6073int checkADname(LDAP *ldap_handle, char *dn_path, char *Name)
6074{
6075  char filter[128];
6076  char *attr_array[3];
6077  int  group_count;
6078  int  rc;
6079  LK_ENTRY  *group_base;
6080 
6081  group_count = 0;
6082  group_base = NULL;
6083 
6084  sprintf(filter, "(sAMAccountName=%s)", Name);
6085  attr_array[0] = "sAMAccountName";
6086  attr_array[1] = NULL;
6087
6088  if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
6089                           &group_base, &group_count,
6090                           LDAP_SCOPE_SUBTREE)) != 0)
6091    {
6092      com_err(whoami, 0, "Unable to process ACE name %s : %s",
6093              Name, ldap_err2string(rc));
6094      return(1);
6095    }
6096
6097  linklist_free(group_base);
6098  group_base = NULL;
6099
6100  if (group_count == 0)
6101    return(0);
6102 
6103  return(1);
6104}
6105
6106#define MAX_ACE 7
6107
6108int ProcessAce(LDAP *ldap_handle, char *dn_path, char *Name, char *Type,
6109               int UpdateGroup, int *ProcessGroup, char *maillist,
6110               char *nfsgroup)
6111{
6112  char  *av[2];
6113  char  GroupName[256];
6114  char  *call_args[7];
6115  int   rc;
6116  char  *AceInfo[4];
6117  char  AceType[32];
6118  char  AceName[128];
6119  char  AceMembership[2];
6120  char  AceOu[256];
6121  char  temp[128];
6122  char  *save_argv[U_END];
6123
6124  if (!SetGroupAce)
6125    {
6126      com_err(whoami, 0, "ProcessAce disabled, skipping");
6127      return(0);
6128    }
6129
6130  strcpy(GroupName, Name);
6131 
6132  if (strcasecmp(Type, "LIST"))
6133    return(1);
6134
6135  while (1)
6136    {
6137      av[0] = GroupName;
6138      AceInfo[0] = AceType;
6139      AceInfo[1] = AceName;
6140      AceInfo[2] = AceMembership;
6141      AceInfo[3] = AceOu;
6142      memset(AceType, '\0', sizeof(AceType));
6143      memset(AceName, '\0', sizeof(AceName));
6144      memset(AceMembership, '\0', sizeof(AceMembership));
6145      memset(AceOu, '\0', sizeof(AceOu));
6146      callback_rc = 0;
6147   
6148      if (rc = mr_query("get_list_info", 1, av, GetAceInfo, AceInfo))
6149        {
6150          if(rc != MR_NO_MATCH)
6151            com_err(whoami, 0, "Unable to get ACE info for list %s : %s",
6152                    GroupName, error_message(rc));
6153
6154          return(1);
6155        }
6156
6157      if (callback_rc)
6158        {
6159          com_err(whoami, 0, "Unable to get ACE info for list %s", GroupName);
6160          return(1);
6161        }
6162
6163      if ((strcasecmp(AceType, "USER")) && (strcasecmp(AceType, "LIST")))
6164        return(0);
6165
6166      strcpy(temp, AceName);
6167
6168      if (!strcasecmp(AceType, "LIST"))
6169        sprintf(temp, "%s%s", AceName, group_suffix);
6170
6171      if (!UpdateGroup)
6172        {
6173          if (checkADname(ldap_handle, dn_path, temp))
6174              return(0);
6175
6176          (*ProcessGroup) = 1;
6177        }
6178
6179      if (!strcasecmp(AceInfo[0], "LIST"))
6180        {
6181          if (make_new_group(ldap_handle, dn_path, "", AceName, AceOu,
6182                             AceMembership, 0, UpdateGroup, maillist,
6183                             nfsgroup))
6184            return(1);
6185
6186          populate_group(ldap_handle, dn_path, AceName, AceOu, AceMembership,
6187                         0, "", 1);
6188        }
6189      else if (!strcasecmp(AceInfo[0], "USER"))
6190        {
6191          av[0] = AceName;
6192          call_args[0] = (char *)ldap_handle;
6193          call_args[1] = dn_path;
6194          call_args[2] = "";
6195          call_args[3] = NULL;
6196          callback_rc = 0;
6197
6198          if(!strcasecmp(AceName, PRODUCTION_PRINCIPAL) ||
6199             !strcasecmp(AceName, TEST_PRINCIPAL))
6200            {
6201              return(1);
6202            }
6203
6204          if (rc = mr_query("get_user_account_by_login", 1, av,
6205                            save_query_info, save_argv))
6206            {
6207              com_err(whoami, 0, "Unable to process user ACE %s for group %s.",
6208                      AceName, Name);
6209              return(1);
6210            }
6211
6212          if (rc = user_create(U_END, save_argv, call_args))
6213            {
6214              com_err(whoami, 0, "Unable to process user ACE %s for group %s.",
6215                      AceName, Name);
6216              return(1);
6217            }
6218         
6219          if (callback_rc)
6220            {
6221              com_err(whoami, 0, "Unable to process user Ace %s for group %s",
6222                      AceName, Name);
6223              return(1);
6224            }
6225
6226          return(0);
6227        }
6228      else
6229        return(1);
6230
6231      if (!strcasecmp(AceType, "LIST"))
6232        {
6233          if (!strcasecmp(GroupName, AceName))
6234            return(0);
6235        }
6236
6237      strcpy(GroupName, AceName);
6238    }
6239 
6240  return(1);
6241}
6242
6243int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId,
6244                   char *group_name, char *group_ou, char *group_membership,
6245                   int group_security_flag, int updateGroup, char *maillist,
6246                   char *nfsgroup)
6247{
6248  char  *av[3];
6249  char  *call_args[8];
6250  int   rc;
6251  LK_ENTRY  *group_base;
6252  int  group_count;
6253  char filter[128];
6254  char *attr_array[3];
6255
6256  av[0] = group_name;
6257  call_args[0] = (char *)ldap_handle;
6258  call_args[1] = dn_path;
6259  call_args[2] = group_name;
6260  call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
6261  call_args[4] = (char *)(long)updateGroup;
6262  call_args[5] = MoiraId;
6263  call_args[6] = "0";
6264  call_args[7] = NULL;
6265  callback_rc = 0;
6266
6267  group_count = 0;
6268  group_base = NULL;
6269
6270  if (rc = mr_query("get_list_info", 1, av, group_create, call_args))
6271    {
6272      moira_disconnect();
6273      com_err(whoami, 0, "Unable to create list %s : %s", group_name,
6274              error_message(rc));
6275      return(rc);
6276    }
6277
6278  if (callback_rc)
6279    {
6280      moira_disconnect();
6281      com_err(whoami, 0, "Unable to create list %s", group_name);
6282      return(callback_rc);
6283    }
6284
6285  return(0);
6286}
6287
6288int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name,
6289                   char *group_ou, char *group_membership,
6290                   int group_security_flag, char *MoiraId,
6291                   int synchronize)
6292{
6293  char      *av[3];
6294  char      *call_args[7];
6295  char      *pUserOu;
6296  LK_ENTRY  *ptr;
6297  int       rc;
6298  char      member[512];
6299  char      *s;
6300  char      **members;
6301  int       i = 0;
6302  int       j = 0;
6303  int       n = 0;
6304  char      group_dn[512];
6305  LDAPMod   *mods[20];
6306  char      *member_v[] = {NULL, NULL};
6307  char      *save_argv[U_END];
6308  char      machine_ou[256];
6309  char      NewMachineName[1024];
6310
6311  com_err(whoami, 0, "Populating group %s", group_name);
6312  av[0] = group_name;
6313  call_args[0] = (char *)ldap_handle;
6314  call_args[1] = dn_path;
6315  call_args[2] = group_name;
6316  call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS |
6317                          MOIRA_MACHINE);
6318  call_args[4] = NULL;
6319  member_base = NULL;
6320  group_members = 0;
6321
6322  if((max_group_members == -1) && !synchronize) {
6323    com_err(whoami, 0, "Skipping populate group for %s", group_name);
6324    return(0);
6325  }
6326
6327  if (rc = mr_query("get_end_members_of_list", 1, av,
6328                    member_list_build, call_args))
6329    {
6330      if(rc == MR_LIST)
6331        return(0);
6332     
6333      com_err(whoami, 0, "Unable to populate list %s : %s",
6334              group_name, error_message(rc));
6335      return(3);
6336    }
6337
6338  if (member_base != NULL)
6339    {
6340      ptr = member_base;
6341
6342      while(ptr != NULL)
6343        {
6344          if (!strcasecmp(ptr->type, "LIST"))
6345            {
6346              ptr = ptr->next;
6347              continue;
6348            }
6349
6350          if (!strcasecmp(ptr->type, "MACHINE") && !ProcessMachineContainer)
6351            {
6352              ptr = ptr->next;
6353              continue;
6354            }
6355
6356          if(!strcasecmp(ptr->type, "USER"))
6357            {
6358              if(!strcasecmp(ptr->member, PRODUCTION_PRINCIPAL) ||
6359                 !strcasecmp(ptr->member, TEST_PRINCIPAL))
6360                {
6361                  ptr = ptr->next;
6362                  continue;
6363                }
6364            }
6365
6366          ptr = ptr->next;
6367          group_members++;
6368        }
6369    }
6370
6371  if(max_group_members && !synchronize && (group_members > max_group_members))
6372    {
6373      com_err(whoami, 0,
6374              "Group %s membership of %d exceeds maximum %d, skipping",
6375              group_name, group_members, max_group_members);
6376      return(0);
6377    }
6378
6379  members = (char **)malloc(sizeof(char *) * 2);
6380
6381  if (member_base != NULL)
6382    {
6383      ptr = member_base;
6384
6385      while (ptr != NULL)
6386        {
6387          if (!strcasecmp(ptr->type, "LIST"))
6388            {
6389              ptr = ptr->next;
6390              continue;
6391            }
6392         
6393          if (!strcasecmp(ptr->type, "MACHINE") && !ProcessMachineContainer)
6394            {
6395              ptr = ptr->next;
6396              continue;
6397            }
6398           
6399          if(!strcasecmp(ptr->type, "USER"))
6400            {
6401              if(!strcasecmp(ptr->member, PRODUCTION_PRINCIPAL) ||
6402                 !strcasecmp(ptr->member, TEST_PRINCIPAL))
6403                {
6404                  ptr = ptr->next;
6405                  continue;
6406                }
6407
6408              if ((rc = check_user(ldap_handle, dn_path, ptr->member,
6409                                   "")) == AD_NO_USER_FOUND)
6410                {
6411                  com_err(whoami, 0, "creating user %s", ptr->member);
6412
6413                  av[0] = ptr->member;
6414                  call_args[0] = (char *)ldap_handle;
6415                  call_args[1] = dn_path;
6416                  call_args[2] = "";
6417                  call_args[3] = NULL;
6418                  callback_rc = 0;
6419                 
6420                  if (rc = mr_query("get_user_account_by_login", 1, av,
6421                                    save_query_info, save_argv))
6422                    {
6423                      com_err(whoami, 0, "Unable to create user %s "
6424                              "while populating group %s.", ptr->member,
6425                              group_name);
6426
6427                      return(3);
6428                    }
6429
6430                  if (rc = user_create(U_END, save_argv, call_args))
6431                    {
6432                      com_err(whoami, 0, "Unable to create user %s "
6433                              "while populating group %s.", ptr->member,
6434                              group_name);
6435                     
6436                      return(3);
6437                    }
6438         
6439                  if (callback_rc)
6440                    {
6441                      com_err(whoami, 0, "Unable to create user %s "
6442                              "while populating group %s", ptr->member,
6443                              group_name);
6444
6445                      return(3);
6446                    }
6447                }
6448
6449              pUserOu = user_ou;
6450                 
6451              if(ActiveDirectory)
6452                {
6453                  sprintf(member, "cn=%s,%s,%s", ptr->member, pUserOu,
6454                          dn_path);
6455                }
6456              else
6457                {
6458                  sprintf(member, "uid=%s,%s,%s", ptr->member, pUserOu,
6459                          dn_path);
6460                }
6461            }
6462          else if (!strcasecmp(ptr->type, "STRING"))
6463            {
6464              if (contact_create(ldap_handle, dn_path, ptr->member,
6465                                 contact_ou))
6466                return(3);
6467
6468              pUserOu = contact_ou;
6469              sprintf(member, "cn=%s,%s,%s", escape_string(ptr->member),
6470                      pUserOu, dn_path);
6471            }
6472          else if (!strcasecmp(ptr->type, "KERBEROS"))
6473            {
6474              if (contact_create(ldap_handle, dn_path, ptr->member,
6475                                 kerberos_ou))
6476                return(3);
6477
6478              pUserOu = kerberos_ou;
6479              sprintf(member, "cn=%s,%s,%s", escape_string(ptr->member),
6480                      pUserOu, dn_path);
6481            }
6482          else if (!strcasecmp(ptr->type, "MACHINE"))
6483            {
6484              memset(machine_ou, '\0', sizeof(machine_ou));
6485              memset(NewMachineName, '\0', sizeof(NewMachineName));
6486
6487              if (!get_machine_ou(ldap_handle, dn_path, ptr->member,
6488                                 machine_ou, NewMachineName))
6489                {
6490                  pUserOu = machine_ou;
6491                  sprintf(member, "cn=%s,%s,%s", NewMachineName, pUserOu,
6492                          dn_path);
6493                }
6494              else
6495                {
6496                  ptr = ptr->next;                 
6497                  continue;
6498                }
6499            }
6500
6501          if(i > 1)
6502            members = (char **)realloc(members, ((i + 2) * sizeof(char *)));
6503          members[i++] = strdup(member);
6504
6505          ptr = ptr->next;
6506        }
6507   
6508      linklist_free(member_base);
6509      member_base = NULL;
6510    }
6511
6512  members[i] = NULL;
6513
6514  sprintf(group_dn, "cn=%s,%s,%s", group_name, group_ou, dn_path);
6515
6516  if(GroupPopulateDelete)
6517    {
6518      n = 0;
6519      ADD_ATTR("member", member_v, LDAP_MOD_REPLACE);
6520      mods[n] = NULL;
6521     
6522      if ((rc = ldap_modify_s(ldap_handle, group_dn,
6523                              mods)) != LDAP_SUCCESS)
6524        {
6525          com_err(whoami, 0,
6526                  "Unable to populate group membership for %s: %s",
6527                  group_dn, ldap_err2string(rc));
6528        }
6529 
6530      for (i = 0; i < n; i++)
6531        free(mods[i]);
6532    }
6533
6534  n = 0;
6535  ADD_ATTR("member", members, LDAP_MOD_REPLACE);
6536  mods[n] = NULL;
6537
6538  if ((rc = ldap_modify_s(ldap_handle, group_dn,
6539                          mods)) != LDAP_SUCCESS)
6540    {
6541      com_err(whoami, 0,
6542              "Unable to populate group membership for %s: %s",
6543              group_dn, ldap_err2string(rc));
6544    }
6545 
6546  for (i = 0; i < n; i++)
6547    free(mods[i]);
6548   
6549  free(members);
6550
6551  return(0);
6552}
6553
6554int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId,
6555                  char *group_name, char *group_ou, char *group_membership,
6556                  int group_security_flag, int type, char *maillist,
6557                  char *nfsgroup)
6558{
6559  char      before_desc[512];
6560  char      before_name[256];
6561  char      before_group_ou[256];
6562  char      before_group_membership[2];
6563  char      distinguishedName[256];
6564  char      ad_distinguishedName[256];
6565  char      filter[128];
6566  char      *attr_array[3];
6567  int       before_security_flag;
6568  int       group_count;
6569  int       rc;
6570  LK_ENTRY  *group_base;
6571  LK_ENTRY  *ptr;
6572  char      ou_both[512];
6573  char      ou_security[512];
6574  char      ou_distribution[512];
6575  char      ou_neither[512];
6576  char      group_dn[512];
6577
6578  memset(ad_distinguishedName, '\0', sizeof(ad_distinguishedName));
6579  sprintf(distinguishedName, "CN=%s,%s,%s", group_name, group_ou, dn_path);
6580
6581  memset(filter, '\0', sizeof(filter));
6582  group_base = NULL;
6583  group_count = 0;
6584
6585  if (rc = ad_get_group(ldap_handle, dn_path, group_name,
6586                        "*", MoiraId,
6587                        "samAccountName", &group_base,
6588                        &group_count, filter))
6589    return(rc);
6590
6591  if (type == CHECK_GROUPS)
6592    {
6593      if (group_count == 1)
6594        {
6595          strcpy(group_dn, group_base->dn);
6596
6597          if (!strcasecmp(group_dn, distinguishedName))
6598            {
6599              linklist_free(group_base);
6600              return(0);
6601            }
6602        }
6603
6604      linklist_free(group_base);
6605
6606      if (group_count == 0)
6607        return(AD_NO_GROUPS_FOUND);
6608
6609      if (group_count == 1)
6610        return(AD_WRONG_GROUP_DN_FOUND);
6611
6612      return(AD_MULTIPLE_GROUPS_FOUND);
6613    }
6614
6615  if (group_count == 0)
6616    {
6617      return(AD_NO_GROUPS_FOUND);
6618    }
6619
6620  if (group_count > 1)
6621    {
6622      ptr = group_base;
6623
6624      strcpy(group_dn, ptr->dn);
6625
6626      while (ptr != NULL)
6627        {
6628          if (!strcasecmp(group_dn, ptr->value))
6629            break;
6630
6631          ptr = ptr->next;
6632        }
6633
6634      if (ptr == NULL)
6635        {
6636          com_err(whoami, 0, "%d groups with moira id = %s", group_count,
6637                  MoiraId);
6638          ptr = group_base;
6639
6640          while (ptr != NULL)
6641            {
6642              com_err(whoami, 0, "%s with moira id = %s", ptr->value, MoiraId);
6643              ptr = ptr->next;
6644            }
6645
6646          linklist_free(group_base);
6647          return(AD_MULTIPLE_GROUPS_FOUND);
6648        }
6649
6650      ptr = group_base;
6651
6652      while (ptr != NULL)
6653        {
6654          strcpy(group_dn, ptr->dn);
6655
6656          if (strcasecmp(group_dn, ptr->value))
6657            rc = ldap_delete_s(ldap_handle, ptr->value);
6658
6659          ptr = ptr->next;
6660        }
6661
6662      linklist_free(group_base);
6663      memset(filter, '\0', sizeof(filter));
6664      group_base = NULL;
6665      group_count = 0;
6666
6667      if (rc = ad_get_group(ldap_handle, dn_path, group_name,
6668                            "*", MoiraId,
6669                            "samAccountName", &group_base,
6670                            &group_count, filter))
6671        return(rc);
6672
6673      if (group_count == 0)
6674        return(AD_NO_GROUPS_FOUND);
6675
6676      if (group_count > 1)
6677        return(AD_MULTIPLE_GROUPS_FOUND);
6678    }
6679
6680  strcpy(ad_distinguishedName, group_base->dn);
6681  linklist_free(group_base);
6682  group_base = NULL;
6683  group_count = 0;
6684
6685  attr_array[0] = "sAMAccountName";
6686  attr_array[1] = NULL;
6687 
6688  if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
6689                           &group_base, &group_count,
6690                           LDAP_SCOPE_SUBTREE)) != 0)
6691    {
6692      com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6693              MoiraId, ldap_err2string(rc));
6694      return(rc);
6695    }
6696 
6697  sprintf(filter, "(sAMAccountName=%s)", group_base->value);
6698
6699  if (!strcasecmp(ad_distinguishedName, distinguishedName))
6700    {
6701      linklist_free(group_base);
6702      group_base = NULL;
6703      group_count = 0;
6704      return(0);
6705    }
6706
6707  linklist_free(group_base);
6708  group_base = NULL;
6709  group_count = 0;
6710  memset(ou_both, '\0', sizeof(ou_both));
6711  memset(ou_security, '\0', sizeof(ou_security));
6712  memset(ou_distribution, '\0', sizeof(ou_distribution));
6713  memset(ou_neither, '\0', sizeof(ou_neither));
6714  memset(before_name, '\0', sizeof(before_name));
6715  memset(before_desc, '\0', sizeof(before_desc));
6716  memset(before_group_membership, '\0', sizeof(before_group_membership));
6717 
6718  attr_array[0] = "name";
6719  attr_array[1] = NULL;
6720
6721  if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
6722                           &group_base, &group_count,
6723                           LDAP_SCOPE_SUBTREE)) != 0)
6724    {
6725      com_err(whoami, 0, "Unable to get list name with MoiraId = %s: %s",
6726              MoiraId, ldap_err2string(rc));
6727      return(rc);
6728    }
6729
6730  strcpy(before_name, group_base->value);
6731  linklist_free(group_base);
6732  group_base = NULL;
6733  group_count = 0;
6734
6735  attr_array[0] = "description";
6736  attr_array[1] = NULL;
6737 
6738  if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
6739                           &group_base, &group_count,
6740                           LDAP_SCOPE_SUBTREE)) != 0)
6741    {
6742      com_err(whoami, 0,
6743              "Unable to get list description with MoiraId = %s: %s",
6744              MoiraId, ldap_err2string(rc));
6745      return(rc);
6746    }
6747
6748  if (group_count != 0)
6749    {
6750      strcpy(before_desc, group_base->value);
6751      linklist_free(group_base);
6752      group_base = NULL;
6753      group_count = 0;
6754    }
6755 
6756  change_to_lower_case(ad_distinguishedName); 
6757  strcpy(ou_both, group_ou_both);
6758  change_to_lower_case(ou_both);
6759  strcpy(ou_security, group_ou_security);
6760  change_to_lower_case(ou_security);
6761  strcpy(ou_distribution, group_ou_distribution);
6762  change_to_lower_case(ou_distribution);
6763  strcpy(ou_neither, group_ou_neither);
6764  change_to_lower_case(ou_neither);
6765
6766  if (strstr(ad_distinguishedName, ou_both))
6767    {
6768      strcpy(before_group_ou, group_ou_both);
6769      before_group_membership[0] = 'B';
6770      before_security_flag = 1;
6771    }
6772  else if (strstr(ad_distinguishedName, ou_security))
6773    {
6774      strcpy(before_group_ou, group_ou_security);
6775      before_group_membership[0] = 'S';
6776      before_security_flag = 1;
6777    }
6778  else if (strstr(ad_distinguishedName, ou_distribution))
6779    {
6780      strcpy(before_group_ou, group_ou_distribution);
6781      before_group_membership[0] = 'D';
6782      before_security_flag = 0;
6783    }
6784  else if (strstr(ad_distinguishedName, ou_neither))
6785    {
6786      strcpy(before_group_ou, group_ou_neither);
6787      before_group_membership[0] = 'N';
6788      before_security_flag = 0;
6789    }
6790  else
6791    return(AD_NO_OU_FOUND);
6792
6793  rc = group_rename(ldap_handle, dn_path, before_name,
6794                    before_group_membership,
6795                    before_group_ou, before_security_flag, before_desc,
6796                    group_name, group_membership, group_ou,
6797                    group_security_flag,
6798                    before_desc, MoiraId, filter, maillist, nfsgroup);
6799
6800  return(rc);
6801}
6802
6803void change_to_lower_case(char *ptr)
6804{
6805  int i;
6806
6807  for (i = 0; i < (int)strlen(ptr); i++)
6808    {
6809      ptr[i] = tolower(ptr[i]);
6810    }
6811}
6812
6813int ad_get_group(LDAP *ldap_handle, char *dn_path,
6814                 char *group_name, char *group_membership,
6815                 char *MoiraId, char *attribute,
6816                 LK_ENTRY **linklist_base, int *linklist_count,
6817                 char *rFilter)
6818{
6819  LK_ENTRY  *pPtr;
6820  char  filter[128];
6821  char  *attr_array[3];
6822  char  *dn;
6823  int   rc;
6824
6825  (*linklist_base) = NULL;
6826  (*linklist_count) = 0;
6827
6828  if (strlen(rFilter) != 0)
6829    {
6830      strcpy(filter, rFilter);
6831      attr_array[0] = attribute;
6832      attr_array[1] = NULL;
6833     
6834      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
6835                               linklist_base, linklist_count,
6836                               LDAP_SCOPE_SUBTREE)) != 0)
6837        {
6838          com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6839                  MoiraId, ldap_err2string(rc));
6840         return(rc);
6841       }
6842
6843    if ((*linklist_count) == 1)
6844      {
6845        strcpy(rFilter, filter);
6846        return(0);
6847      }
6848    }
6849
6850  linklist_free((*linklist_base));
6851  (*linklist_base) = NULL;
6852  (*linklist_count) = 0;
6853
6854  if (strlen(MoiraId) != 0)
6855    {
6856      sprintf(filter, "(&(objectClass=group)(mitMoiraId=%s))", MoiraId);
6857
6858      attr_array[0] = attribute;
6859      attr_array[1] = NULL;
6860
6861      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
6862                               linklist_base, linklist_count,
6863                               LDAP_SCOPE_SUBTREE)) != 0)
6864        {
6865          com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6866                  MoiraId, ldap_err2string(rc));
6867         return(rc);
6868       }
6869    }
6870
6871  if ((*linklist_count) > 1)
6872    {
6873      com_err(whoami, 0, "multiple groups with mitMoiraId = %s", MoiraId);
6874      pPtr = (*linklist_base);
6875
6876      while (pPtr)
6877        {
6878          com_err(whoami, 0, "groups %s has mitMoiraId = %s", pPtr->value,
6879                  MoiraId);
6880          pPtr = pPtr->next;
6881        }
6882
6883      linklist_free((*linklist_base));
6884      (*linklist_base) = NULL;
6885      (*linklist_count) = 0;
6886    }
6887
6888  if ((*linklist_count) == 1)
6889    {
6890
6891      pPtr = (*linklist_base);
6892      dn = strdup(pPtr->dn);
6893      dn += 3;
6894
6895      if (!memcmp(dn, group_name, strlen(group_name)))
6896        {
6897          strcpy(rFilter, filter);
6898          return(0);
6899        }
6900    }
6901
6902  linklist_free((*linklist_base));
6903  (*linklist_base) = NULL;
6904  (*linklist_count) = 0;
6905  sprintf(filter, "(sAMAccountName=%s%s)", group_name, group_suffix);
6906
6907  attr_array[0] = attribute;
6908  attr_array[1] = NULL;
6909
6910  if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
6911                           linklist_base, linklist_count,
6912                           LDAP_SCOPE_SUBTREE)) != 0)
6913    {
6914      com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6915              MoiraId, ldap_err2string(rc));
6916      return(rc);
6917    }
6918
6919  if ((*linklist_count) == 1)
6920    {
6921      strcpy(rFilter, filter);
6922      return(0);
6923    }
6924
6925  return(0);
6926}
6927
6928int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, char *MoiraId)
6929{
6930  char filter[128];
6931  char *attr_array[3];
6932  char SamAccountName[64];
6933  int  group_count;
6934  int  rc;
6935  LK_ENTRY  *group_base;
6936  LK_ENTRY  *gPtr;
6937
6938  group_count = 0;
6939  group_base = NULL;
6940
6941  if (strlen(MoiraId) != 0)
6942    {
6943      sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
6944
6945      attr_array[0] = "sAMAccountName";
6946      attr_array[1] = NULL;
6947      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
6948                               &group_base, &group_count,
6949                               LDAP_SCOPE_SUBTREE)) != 0)
6950        {
6951          com_err(whoami, 0, "Unable to process user %s : %s",
6952                  UserName, ldap_err2string(rc));
6953          return(rc);
6954        }
6955
6956      if (group_count > 1)
6957        {
6958          com_err(whoami, 0, "multiple users exist with MoiraId = %s",
6959                  MoiraId);
6960          gPtr = group_base;
6961
6962          while (gPtr)
6963            {
6964              com_err(whoami, 0, "user %s exist with MoiraId = %s",
6965                      gPtr->value, MoiraId);
6966              gPtr = gPtr->next;
6967            }
6968        }
6969    }
6970
6971  if (group_count != 1)
6972    {
6973      linklist_free(group_base);
6974      group_count = 0;
6975      group_base = NULL;
6976      sprintf(filter, "(sAMAccountName=%s)", UserName);
6977      attr_array[0] = "sAMAccountName";
6978      attr_array[1] = NULL;
6979
6980      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
6981                               &group_base, &group_count,
6982                               LDAP_SCOPE_SUBTREE)) != 0)
6983        {
6984          com_err(whoami, 0, "Unable to process user %s : %s",
6985                  UserName, ldap_err2string(rc));
6986          return(rc);
6987        }
6988    }
6989
6990  if (group_count != 1)
6991    {
6992      linklist_free(group_base);
6993      return(AD_NO_USER_FOUND);
6994    }
6995
6996  strcpy(SamAccountName, group_base->value);
6997  linklist_free(group_base);
6998  group_count = 0;
6999  rc = 0;
7000
7001  if (strcmp(SamAccountName, UserName))
7002    {
7003      com_err(whoami, 0,
7004              "User object %s with MoiraId %s has mismatched usernames "
7005              "(LDAP username %s, Moira username %s)", SamAccountName,
7006              MoiraId, SamAccountName, UserName);
7007    }
7008
7009  return(0);
7010}
7011
7012void container_get_dn(char *src, char *dest)
7013{
7014  char *sPtr;
7015  char *array[20];
7016  char name[256];
7017  int  n;
7018
7019  memset(array, '\0', 20 * sizeof(array[0]));
7020
7021  if (strlen(src) == 0)
7022    return;
7023
7024  strcpy(name, src);
7025  sPtr = name;
7026  n = 0;
7027  array[n] = name;
7028  ++n;
7029
7030  while (*sPtr)
7031    {
7032      if ((*sPtr) == '/')
7033        {
7034          (*sPtr) = '\0';
7035          ++sPtr;
7036          array[n] = sPtr;
7037          ++n;
7038        }
7039      else
7040        ++sPtr;
7041    }
7042
7043  strcpy(dest, "OU=");
7044
7045  while (n != 0)
7046    {
7047      strcat(dest, array[n-1]);
7048      --n;
7049      if (n > 0)
7050        {
7051          strcat(dest, ",OU=");
7052        }
7053    }
7054
7055  return;
7056}
7057
7058void container_get_name(char *src, char *dest)
7059{
7060  char *sPtr;
7061  char *dPtr;
7062
7063  if (strlen(src) == 0)
7064    return;
7065
7066  sPtr = src;
7067  dPtr = src;
7068
7069  while (*sPtr)
7070    {
7071      if ((*sPtr) == '/')
7072        {
7073          dPtr = sPtr;
7074          ++dPtr;
7075        }
7076      ++sPtr;
7077    }
7078
7079  strcpy(dest, dPtr);
7080  return;
7081}
7082
7083void container_check(LDAP *ldap_handle, char *dn_path, char *name)
7084{
7085  char cName[256];
7086  char *av[7];
7087  int  i;
7088  int  rc;
7089
7090  strcpy(cName, name);
7091
7092  for (i = 0; i < (int)strlen(cName); i++)
7093    {
7094      if (cName[i] == '/')
7095        {
7096          cName[i] = '\0';
7097          av[CONTAINER_NAME] = cName;
7098          av[CONTAINER_DESC] = "";
7099          av[CONTAINER_LOCATION] = "";
7100          av[CONTAINER_CONTACT] = "";
7101          av[CONTAINER_TYPE] = "";
7102          av[CONTAINER_ID] = "";
7103          av[CONTAINER_ROWID] = "";
7104          rc = container_create(ldap_handle, dn_path, 7, av);
7105
7106          if (rc == LDAP_SUCCESS)
7107            {
7108              com_err(whoami, 0, "container %s created without a mitMoiraId",
7109                      cName);
7110            }
7111
7112          cName[i] = '/';
7113        }
7114    }
7115}
7116
7117int container_rename(LDAP *ldap_handle, char *dn_path, int beforec,
7118                     char **before, int afterc, char **after)
7119{
7120  char      dName[256];
7121  char      cName[256];
7122  char      new_cn[128];
7123  char      new_dn_path[256];
7124  char      temp[256];
7125  char      distinguishedName[256];
7126  char      *pPtr;
7127  int       rc;
7128  int       i;
7129
7130  memset(cName, '\0', sizeof(cName));
7131  container_get_name(after[CONTAINER_NAME], cName);
7132
7133  if (!check_container_name(cName))
7134    {
7135      com_err(whoami, 0, "Unable to process invalid LDAP container name %s",
7136              cName);
7137      return(AD_INVALID_NAME);
7138    }
7139
7140  memset(distinguishedName, '\0', sizeof(distinguishedName));
7141
7142  if (rc = container_get_distinguishedName(ldap_handle, dn_path,
7143                                           distinguishedName, beforec, before))
7144    return(rc);
7145
7146  if (strlen(distinguishedName) == 0)
7147    {
7148      rc = container_create(ldap_handle, dn_path, afterc, after);
7149      return(rc);
7150    }
7151
7152  strcpy(temp, after[CONTAINER_NAME]);
7153  pPtr = temp;
7154
7155  for (i = 0; i < (int)strlen(temp); i++)
7156    {
7157      if (temp[i] == '/')
7158        {
7159          pPtr = &temp[i];
7160        }
7161    }
7162
7163  (*pPtr) = '\0';
7164
7165  container_get_dn(temp, dName);
7166
7167  if (strlen(temp) != 0)
7168    sprintf(new_dn_path, "%s,%s", dName, dn_path);
7169  else
7170    sprintf(new_dn_path, "%s", dn_path);
7171
7172  sprintf(new_cn, "OU=%s", cName);
7173
7174  container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
7175
7176  if ((rc = ldap_rename_s(ldap_handle, distinguishedName, new_cn, new_dn_path,
7177                          TRUE, NULL, NULL)) != LDAP_SUCCESS)
7178    {
7179      com_err(whoami, 0, "Unable to rename container from %s to %s : %s",
7180              before[CONTAINER_NAME], after[CONTAINER_NAME],
7181              ldap_err2string(rc));
7182      return(rc);
7183    }
7184
7185  memset(dName, '\0', sizeof(dName));
7186  container_get_dn(after[CONTAINER_NAME], dName);
7187  rc = container_adupdate(ldap_handle, dn_path, dName, "", afterc, after);
7188
7189  return(rc);
7190}
7191
7192int container_delete(LDAP *ldap_handle, char *dn_path, int count, char **av)
7193{
7194  char      distinguishedName[256];
7195  int       rc;
7196
7197  memset(distinguishedName, '\0', sizeof(distinguishedName));
7198
7199  if (rc = container_get_distinguishedName(ldap_handle, dn_path,
7200                                           distinguishedName, count, av))
7201    return(rc);
7202
7203  if (strlen(distinguishedName) == 0)
7204    return(0);
7205
7206  if ((rc = ldap_delete_s(ldap_handle, distinguishedName)) != LDAP_SUCCESS)
7207    {
7208      if (rc == LDAP_NOT_ALLOWED_ON_NONLEAF)
7209        container_move_objects(ldap_handle, dn_path, distinguishedName);
7210      else
7211        com_err(whoami, 0, "Unable to delete container %s from directory : %s",
7212                av[CONTAINER_NAME], ldap_err2string(rc));
7213    }
7214
7215  return(rc);
7216}
7217
7218int container_create(LDAP *ldap_handle, char *dn_path, int count, char **av)
7219{
7220  char      *attr_array[3];
7221  LK_ENTRY  *group_base;
7222  int       group_count;
7223  LDAPMod   *mods[20];
7224  char      *objectClass_v[] = {"top",
7225                           "organizationalUnit",
7226                           NULL};
7227
7228  char *ou_v[] = {NULL, NULL};
7229  char *name_v[] = {NULL, NULL};
7230  char *moiraId_v[] = {NULL, NULL};
7231  char *desc_v[] = {NULL, NULL};
7232  char *managedBy_v[] = {NULL, NULL};
7233  char dName[256];
7234  char cName[256];
7235  char managedByDN[256];
7236  char filter[256];
7237  char temp[256];
7238  int  n;
7239  int  i;
7240  int  rc;
7241   
7242  memset(filter, '\0', sizeof(filter));
7243  memset(dName, '\0', sizeof(dName));
7244  memset(cName, '\0', sizeof(cName));
7245  memset(managedByDN, '\0', sizeof(managedByDN));
7246  container_get_dn(av[CONTAINER_NAME], dName);
7247  container_get_name(av[CONTAINER_NAME], cName);
7248
7249  if ((strlen(cName) == 0) || (strlen(dName) == 0))
7250    {
7251      com_err(whoami, 0, "Unable to process invalid LDAP container name %s",
7252              cName);
7253      return(AD_INVALID_NAME);
7254    }
7255
7256  if (!check_container_name(cName))
7257    {
7258      com_err(whoami, 0, "Unable to process invalid LDAP container name %s",
7259              cName);
7260      return(AD_INVALID_NAME);
7261    }
7262
7263  n = 0;
7264  ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
7265  name_v[0] = cName;
7266  ADD_ATTR("name", name_v, LDAP_MOD_ADD);
7267  ou_v[0] = cName;
7268  ADD_ATTR("ou", ou_v, LDAP_MOD_ADD);
7269
7270  if (strlen(av[CONTAINER_ROWID]) != 0)
7271    {
7272      moiraId_v[0] = av[CONTAINER_ROWID];
7273      ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_ADD);
7274    }
7275
7276  if (strlen(av[CONTAINER_DESC]) != 0)
7277    {
7278      desc_v[0] = av[CONTAINER_DESC];
7279      ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
7280    }
7281
7282  if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
7283    {
7284      if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
7285        {
7286          if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID],
7287                              kerberos_ou))
7288            {
7289              sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID],
7290                      kerberos_ou, dn_path);
7291              managedBy_v[0] = managedByDN;
7292              ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
7293            }
7294        }
7295      else
7296        {
7297          if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
7298            {
7299              sprintf(filter, "(&(cn=%s)(&(objectCategory=person)"
7300                      "(objectClass=user)))", av[CONTAINER_ID]);
7301            }
7302
7303          if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
7304            {
7305              sprintf(filter, "(&(objectClass=group)(cn=%s))",
7306                      av[CONTAINER_ID]);
7307            }
7308
7309          if (strlen(filter) != 0)
7310            {
7311              attr_array[0] = "distinguishedName";
7312              attr_array[1] = NULL;
7313              group_count = 0;
7314              group_base = NULL;
7315              if ((rc = linklist_build(ldap_handle, dn_path, filter,
7316                                       attr_array,
7317                                       &group_base, &group_count,
7318                                       LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7319                {
7320                  if (group_count == 1)
7321                    {
7322                      strcpy(managedByDN, group_base->value);
7323                      managedBy_v[0] = managedByDN;
7324                      ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
7325                    }
7326                  linklist_free(group_base);
7327                  group_base = NULL;
7328                  group_count = 0;
7329                }
7330            }
7331        }
7332    }
7333 
7334  mods[n] = NULL;
7335
7336  sprintf(temp, "%s,%s", dName, dn_path);
7337  rc = ldap_add_ext_s(ldap_handle, temp, mods, NULL, NULL);
7338 
7339  for (i = 0; i < n; i++)
7340    free(mods[i]);
7341 
7342  if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
7343    {
7344      com_err(whoami, 0, "Unable to create container %s : %s",
7345              cName, ldap_err2string(rc));
7346      return(rc);
7347    }
7348
7349  if (rc == LDAP_ALREADY_EXISTS)
7350    {
7351      if (strlen(av[CONTAINER_ROWID]) != 0)
7352        rc = container_adupdate(ldap_handle, dn_path, dName, "", count, av);
7353    }
7354
7355  return(rc);
7356}
7357
7358int container_update(LDAP *ldap_handle, char *dn_path, int beforec,
7359                     char **before, int afterc, char **after)
7360{
7361  char distinguishedName[256];
7362  int  rc;
7363
7364  memset(distinguishedName, '\0', sizeof(distinguishedName));
7365
7366  if (rc = container_get_distinguishedName(ldap_handle, dn_path,
7367                                           distinguishedName, afterc, after))
7368    return(rc);
7369
7370  if (strlen(distinguishedName) == 0)
7371    {
7372      rc = container_create(ldap_handle, dn_path, afterc, after);
7373      return(rc);
7374    }
7375 
7376  container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
7377  rc = container_adupdate(ldap_handle, dn_path, "", distinguishedName, afterc,
7378                          after);
7379
7380  return(rc);
7381}
7382
7383int container_get_distinguishedName(LDAP *ldap_handle, char *dn_path,
7384                                    char *distinguishedName, int count,
7385                                    char **av)
7386{
7387  char      *attr_array[3];
7388  LK_ENTRY  *group_base;
7389  int       group_count;
7390  char      dName[256];
7391  char      cName[256];
7392  char      filter[512];
7393  int       rc;
7394
7395  memset(filter, '\0', sizeof(filter));
7396  memset(dName, '\0', sizeof(dName));
7397  memset(cName, '\0', sizeof(cName));
7398  container_get_dn(av[CONTAINER_NAME], dName);
7399  container_get_name(av[CONTAINER_NAME], cName);
7400
7401  if (strlen(dName) == 0)
7402    {
7403      com_err(whoami, 0, "Unable to process invalid LDAP container name %s",
7404              av[CONTAINER_NAME]);
7405      return(AD_INVALID_NAME);
7406    }
7407
7408  if (!check_container_name(cName))
7409    {
7410      com_err(whoami, 0, "Unable to process invalid LDAP container name %s",
7411              cName);
7412      return(AD_INVALID_NAME);
7413    }
7414 
7415  sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))",
7416          av[CONTAINER_ROWID]);
7417  attr_array[0] = "distinguishedName";
7418  attr_array[1] = NULL;
7419  group_count = 0;
7420  group_base = NULL;
7421
7422  if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
7423                           &group_base, &group_count,
7424                           LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7425    {
7426      if (group_count == 1)
7427        {
7428          strcpy(distinguishedName, group_base->value);
7429        }
7430
7431      linklist_free(group_base);
7432      group_base = NULL;
7433      group_count = 0;
7434    }
7435
7436  if (strlen(distinguishedName) == 0)
7437    {
7438      sprintf(filter, "(&(objectClass=organizationalUnit)"
7439              "(distinguishedName=%s,%s))", dName, dn_path);
7440      attr_array[0] = "distinguishedName";
7441      attr_array[1] = NULL;
7442      group_count = 0;
7443      group_base = NULL;
7444
7445      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
7446                               &group_base, &group_count,
7447                               LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7448        {
7449          if (group_count == 1)
7450            {
7451              strcpy(distinguishedName, group_base->value);
7452            }
7453
7454          linklist_free(group_base);
7455          group_base = NULL;
7456          group_count = 0;
7457        }
7458    }
7459
7460  return(0);
7461}
7462
7463int container_adupdate(LDAP *ldap_handle, char *dn_path, char *dName,
7464                       char *distinguishedName, int count, char **av)
7465{
7466  char      *attr_array[5];
7467  LK_ENTRY  *group_base;
7468  LK_ENTRY  *pPtr;
7469  LDAPMod   *mods[20];
7470  int       group_count;
7471  char      filter[512];
7472  char      *moiraId_v[] = {NULL, NULL};
7473  char      *desc_v[] = {NULL, NULL};
7474  char      *managedBy_v[] = {NULL, NULL};
7475  char      managedByDN[256];
7476  char      moiraId[64];
7477  char      desc[256];
7478  char      ad_path[512];
7479  int       rc;
7480  int       i;
7481  int       n;
7482
7483
7484  strcpy(ad_path, distinguishedName);
7485
7486  if (strlen(dName) != 0)
7487    sprintf(ad_path, "%s,%s", dName, dn_path);
7488
7489  sprintf(filter, "(&(objectClass=organizationalUnit)(distinguishedName=%s))",
7490          ad_path);
7491
7492  if (strlen(av[CONTAINER_ID]) != 0)
7493    sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))",
7494            av[CONTAINER_ROWID]);
7495
7496  attr_array[0] = "mitMoiraId";
7497  attr_array[1] = "description";
7498  attr_array[2] = "managedBy";
7499  attr_array[3] = NULL;
7500  group_count = 0;
7501  group_base = NULL;
7502
7503  if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
7504                           &group_base, &group_count,
7505                           LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
7506    {
7507      com_err(whoami, 0, "Unable to retreive container info for %s : %s",
7508              av[CONTAINER_NAME], ldap_err2string(rc));
7509      return(rc);
7510    }
7511
7512  memset(managedByDN, '\0', sizeof(managedByDN));
7513  memset(moiraId, '\0', sizeof(moiraId));
7514  memset(desc, '\0', sizeof(desc));
7515  pPtr = group_base;
7516
7517  while (pPtr)
7518    {
7519      if (!strcasecmp(pPtr->attribute, "description"))
7520        strcpy(desc, pPtr->value);
7521      else if (!strcasecmp(pPtr->attribute, "managedBy"))
7522        strcpy(managedByDN, pPtr->value);
7523      else if (!strcasecmp(pPtr->attribute, "mitMoiraId"))
7524        strcpy(moiraId, pPtr->value);
7525      pPtr = pPtr->next;
7526    }
7527
7528  linklist_free(group_base);
7529  group_base = NULL;
7530  group_count = 0;
7531
7532  n = 0;
7533  if (strlen(av[CONTAINER_ROWID]) != 0)
7534    {
7535      moiraId_v[0] = av[CONTAINER_ROWID];
7536      ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_REPLACE);
7537    }
7538
7539  if (strlen(av[CONTAINER_DESC]) != 0)
7540    {
7541      attribute_update(ldap_handle, ad_path, av[CONTAINER_DESC], "description",
7542                       dName);
7543    }
7544  else
7545    {
7546      if (strlen(desc) != 0)
7547        {
7548          attribute_update(ldap_handle, ad_path, "", "description", dName);
7549        }
7550    }
7551
7552  if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
7553    {
7554      if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
7555        {
7556          if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID],
7557                              kerberos_ou))
7558            {
7559              sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID],
7560                      kerberos_ou, dn_path);
7561              managedBy_v[0] = managedByDN;
7562              ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
7563            }
7564          else
7565            {
7566              if (strlen(managedByDN) != 0)
7567                {
7568                  attribute_update(ldap_handle, ad_path, "", "managedBy",
7569                                   dName);
7570                }
7571            }
7572        }
7573      else
7574        {
7575          memset(filter, '\0', sizeof(filter));
7576
7577          if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
7578            {
7579              sprintf(filter, "(&(cn=%s)(&(objectCategory=person)"
7580                      "(objectClass=user)))", av[CONTAINER_ID]);
7581            }
7582
7583          if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
7584            {
7585              sprintf(filter, "(&(objectClass=group)(cn=%s))",
7586                      av[CONTAINER_ID]);
7587            }
7588
7589          if (strlen(filter) != 0)
7590            {
7591              attr_array[0] = "distinguishedName";
7592              attr_array[1] = NULL;
7593              group_count = 0;
7594              group_base = NULL;
7595              if ((rc = linklist_build(ldap_handle, dn_path, filter,
7596                                       attr_array, &group_base, &group_count,
7597                                       LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7598                {
7599                  if (group_count == 1)
7600                    {
7601                      strcpy(managedByDN, group_base->value);
7602                      managedBy_v[0] = managedByDN;
7603                      ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
7604                    }
7605                  else
7606                    {
7607                      if (strlen(managedByDN) != 0)
7608                        {
7609                          attribute_update(ldap_handle, ad_path, "",
7610                                           "managedBy", dName);
7611                        }
7612                    }
7613
7614                  linklist_free(group_base);
7615                  group_base = NULL;
7616                  group_count = 0;
7617                }
7618            }
7619          else
7620            {
7621              if (strlen(managedByDN) != 0)
7622                {
7623                  attribute_update(ldap_handle, ad_path, "", "managedBy",
7624                                   dName);
7625                }
7626            }
7627        }
7628    }
7629
7630  mods[n] = NULL;
7631
7632  if (n == 0)
7633    return(LDAP_SUCCESS);
7634
7635  rc = ldap_modify_s(ldap_handle, ad_path, mods);
7636
7637  for (i = 0; i < n; i++)
7638    free(mods[i]);
7639
7640  if (rc != LDAP_SUCCESS)
7641    {
7642      com_err(whoami, 0, "Unable to modify container info for %s : %s",
7643              av[CONTAINER_NAME], ldap_err2string(rc));
7644      return(rc);
7645    }
7646 
7647  return(rc);
7648}
7649
7650int container_move_objects(LDAP *ldap_handle, char *dn_path, char *dName)
7651{
7652  char      *attr_array[3];
7653  LK_ENTRY  *group_base;
7654  LK_ENTRY  *pPtr;
7655  int       group_count;
7656  char      filter[512];
7657  char      new_cn[128];
7658  char      temp[256];
7659  int       rc;
7660  int       NumberOfEntries = 10;
7661  int       i;
7662  int       count;
7663
7664  rc = ldap_set_option(ldap_handle, LDAP_OPT_SIZELIMIT, &NumberOfEntries);
7665
7666  for (i = 0; i < 3; i++)
7667    {
7668      memset(filter, '\0', sizeof(filter));
7669
7670      if (i == 0)
7671        {
7672          strcpy(filter, "(!(|(objectClass=computer)"
7673                 "(objectClass=organizationalUnit)))");
7674          attr_array[0] = "cn";
7675          attr_array[1] = NULL;
7676        }
7677      else if (i == 1)
7678        {
7679          strcpy(filter, "(objectClass=computer)");
7680          attr_array[0] = "cn";
7681          attr_array[1] = NULL;
7682        }
7683      else
7684        {
7685          strcpy(filter, "(objectClass=organizationalUnit)");
7686          attr_array[0] = "ou";
7687          attr_array[1] = NULL;
7688        }
7689
7690      while (1)
7691        {
7692          if ((rc = linklist_build(ldap_handle, dName, filter, attr_array,
7693                                   &group_base, &group_count,
7694                                   LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
7695            {
7696              break;
7697            }
7698
7699          if (group_count == 0)
7700            break;
7701
7702          pPtr = group_base;
7703
7704          while(pPtr)
7705            {
7706              if (!strcasecmp(pPtr->attribute, "cn"))
7707                {
7708                  sprintf(new_cn, "cn=%s", pPtr->value);
7709                  if (i == 0)
7710                    sprintf(temp, "%s,%s", orphans_other_ou, dn_path);
7711                  if (i == 1)
7712                    sprintf(temp, "%s,%s", orphans_machines_ou, dn_path);
7713                  count = 1;
7714
7715                  while (1)
7716                    {
7717                      rc = ldap_rename_s(ldap_handle, pPtr->dn, new_cn, temp,
7718                                         TRUE, NULL, NULL);
7719                      if (rc == LDAP_ALREADY_EXISTS)
7720                        {
7721                          sprintf(new_cn, "cn=%s_%d", pPtr->value, count);
7722                          ++count;
7723                        }
7724                      else
7725                        break;
7726                    }
7727                }
7728              else if (!strcasecmp(pPtr->attribute, "ou"))
7729                {
7730                  rc = ldap_delete_s(ldap_handle, pPtr->dn);
7731                }
7732
7733              pPtr = pPtr->next;
7734            }
7735
7736          linklist_free(group_base);
7737          group_base = NULL;
7738          group_count = 0;
7739        }
7740    }
7741
7742  return(0);
7743}
7744
7745int get_machine_ou(LDAP *ldap_handle, char *dn_path, char *member,
7746                   char *machine_ou, char *NewMachineName)
7747{
7748  LK_ENTRY  *group_base;
7749  int  group_count;
7750  int  i;
7751  char filter[128];
7752  char *attr_array[3];
7753  char cn[256];
7754  char dn[256];
7755  char temp[256];
7756  char *pPtr;
7757  int   rc;
7758
7759  strcpy(NewMachineName, member);
7760  rc = moira_connect();
7761  rc = GetMachineName(NewMachineName);
7762  moira_disconnect();
7763
7764  if (strlen(NewMachineName) == 0)
7765    {
7766      com_err(whoami, 0, "Unable to find alais for machine %s in Moira",
7767              member);
7768      return(1);
7769    }
7770
7771  pPtr = NULL;
7772  pPtr = strchr(NewMachineName, '.');
7773
7774  if (pPtr != NULL)
7775    (*pPtr) = '\0';
7776
7777  group_base = NULL;
7778  group_count = 0;
7779  sprintf(filter, "(sAMAccountName=%s$)", NewMachineName);
7780  attr_array[0] = "cn";
7781  attr_array[1] = NULL;
7782  sprintf(temp, "%s", dn_path);
7783
7784  if ((rc = linklist_build(ldap_handle, temp, filter, attr_array,
7785                           &group_base, &group_count,
7786                           LDAP_SCOPE_SUBTREE)) != 0)
7787    {
7788      com_err(whoami, 0, "Unable to process machine %s : %s",
7789              member, ldap_err2string(rc));
7790      return(1);
7791    }
7792
7793  if (group_count != 1)
7794    {
7795      return(1);
7796    }
7797
7798  strcpy(dn, group_base->dn);
7799  strcpy(cn, group_base->value);
7800
7801  for (i = 0; i < (int)strlen(dn); i++)
7802    dn[i] = tolower(dn[i]);
7803
7804  for (i = 0; i < (int)strlen(cn); i++)
7805    cn[i] = tolower(cn[i]);
7806
7807  linklist_free(group_base);
7808  pPtr = NULL;
7809  pPtr = strstr(dn, cn);
7810
7811  if (pPtr == NULL)
7812    {
7813      com_err(whoami, 0, "Unable to process machine %s",
7814              member);
7815      return(1);
7816    }
7817
7818  pPtr += strlen(cn) + 1;
7819  strcpy(machine_ou, pPtr);
7820  pPtr = NULL;
7821  pPtr = strstr(machine_ou, "dc=");
7822
7823  if (pPtr == NULL)
7824    {
7825      com_err(whoami, 0, "Unable to process machine %s",
7826              member);
7827      return(1);
7828    }
7829
7830  --pPtr;
7831  (*pPtr) = '\0';
7832
7833  return(0);
7834}
7835
7836int machine_move_to_ou(LDAP *ldap_handle, char * dn_path,
7837                       char *MoiraMachineName, char *DestinationOu)
7838{
7839  char        NewCn[128];
7840  char        OldDn[512];
7841  char        MachineName[128];
7842  char        filter[128];
7843  char        *attr_array[3];
7844  char        NewOu[256];
7845  char        *cPtr = NULL;
7846  int         group_count;
7847  long        rc;
7848  LK_ENTRY    *group_base;
7849
7850  group_count = 0;
7851  group_base = NULL;
7852 
7853  strcpy(MachineName, MoiraMachineName);
7854  rc = GetMachineName(MachineName);
7855
7856  if (strlen(MachineName) == 0)
7857    {
7858      com_err(whoami, 0, "Unable to find alais for machine %s in Moira",
7859              MoiraMachineName);
7860      return(1);
7861    }
7862 
7863  cPtr = strchr(MachineName, '.');
7864
7865  if (cPtr != NULL)
7866    (*cPtr) = '\0';
7867
7868  sprintf(filter, "(sAMAccountName=%s$)", MachineName);
7869  attr_array[0] = "sAMAccountName";
7870  attr_array[1] = NULL;
7871
7872  if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
7873                           &group_base,
7874                           &group_count, LDAP_SCOPE_SUBTREE)) != 0)
7875    {
7876      com_err(whoami, 0, "Unable to process machine %s : %s",
7877              MoiraMachineName, ldap_err2string(rc));
7878      return(1);
7879    }
7880 
7881  if (group_count == 1)
7882    strcpy(OldDn, group_base->dn);
7883
7884  linklist_free(group_base);
7885  group_base = NULL;
7886
7887  if (group_count != 1)
7888    {
7889      com_err(whoami, 0, "Unable to find machine %s in directory: %s",
7890              MoiraMachineName);
7891      return(1);
7892    }
7893
7894  sprintf(NewOu, "%s,%s", DestinationOu, dn_path);
7895  cPtr = strchr(OldDn, ',');
7896
7897  if (cPtr != NULL)
7898    {
7899      ++cPtr;
7900      if (!strcasecmp(cPtr, NewOu))
7901        return(0);
7902    }
7903
7904  sprintf(NewCn, "CN=%s", MachineName);
7905  rc = ldap_rename_s(ldap_handle, OldDn, NewCn, NewOu, TRUE, NULL, NULL);
7906
7907  return(rc);
7908}
7909
7910int machine_check(LDAP *ldap_handle, char *dn_path, char *machine_name)
7911{
7912  char    Name[128];
7913  char    *pPtr;
7914  int     rc;
7915 
7916  memset(Name, '\0', sizeof(Name));
7917  strcpy(Name, machine_name);
7918  pPtr = NULL;
7919  pPtr = strchr(Name, '.');
7920
7921  if (pPtr != NULL)
7922    (*pPtr) = '\0';
7923
7924  strcat(Name, "$");
7925  return(!(rc = checkADname(ldap_handle, dn_path, Name)));
7926}
7927
7928int machine_get_moira_container(LDAP *ldap_handle, char *dn_path,
7929                                char *machine_name, char *container_name)
7930{
7931  int     rc;
7932  char    *av[2];
7933  char    *call_args[2];
7934 
7935  av[0] = machine_name;
7936  call_args[0] = (char *)container_name;
7937  rc = mr_query("get_machine_to_container_map", 1, av,
7938                machine_GetMoiraContainer, call_args);
7939  return(rc);
7940}
7941
7942int machine_GetMoiraContainer(int ac, char **av, void *ptr)
7943{
7944  char **call_args;
7945 
7946  call_args = ptr;
7947  strcpy(call_args[0], av[1]);
7948  return(0);
7949}
7950
7951int Moira_container_group_create(char **after)
7952{
7953  long rc;
7954  char GroupName[64];
7955  char *argv[20];
7956 
7957  memset(GroupName, '\0', sizeof(GroupName));
7958  rc = Moira_groupname_create(GroupName, after[CONTAINER_NAME],
7959                              after[CONTAINER_ROWID]);
7960  if (rc)
7961    return rc;
7962 
7963  argv[L_NAME] = GroupName;
7964  argv[L_ACTIVE] = "1";
7965  argv[L_PUBLIC] = "0";
7966  argv[L_HIDDEN] = "0";
7967  argv[L_MAILLIST] = "0";
7968  argv[L_GROUP] = "1";
7969  argv[L_GID] = UNIQUE_GID;
7970  argv[L_NFSGROUP] = "0";
7971  argv[L_MAILMAN] = "0";
7972  argv[L_MAILMAN_SERVER] = "[NONE]";
7973  argv[L_DESC] = "auto created container group";
7974  argv[L_ACE_TYPE] = "USER";
7975  argv[L_MEMACE_TYPE] = "USER";
7976  argv[L_ACE_NAME] = "sms";
7977  argv[L_MEMACE_NAME] = "sms";
7978
7979  if (rc = mr_query("add_list", 15, argv, NULL, NULL))
7980    {
7981      com_err(whoami, 0,
7982              "Unable to create container group %s for container %s: %s",
7983              GroupName, after[CONTAINER_NAME], error_message(rc));
7984    }
7985
7986  Moira_setContainerGroup(after[CONTAINER_NAME], GroupName);
7987  Moira_addGroupToParent(after[CONTAINER_NAME], GroupName);
7988 
7989  return(rc);
7990}
7991
7992int Moira_container_group_update(char **before, char **after)
7993{
7994  long rc;
7995  char BeforeGroupName[64];
7996  char AfterGroupName[64];
7997  char *argv[20];
7998 
7999  if (!strcasecmp(after[CONTAINER_NAME], before[CONTAINER_NAME]))
8000    return(0);
8001
8002  memset(BeforeGroupName, '\0', sizeof(BeforeGroupName));
8003  Moira_getGroupName(after[CONTAINER_NAME], BeforeGroupName, 0);
8004  if (strlen(BeforeGroupName) == 0)
8005    return(0);
8006
8007  memset(AfterGroupName, '\0', sizeof(AfterGroupName));
8008  rc = Moira_groupname_create(AfterGroupName, after[CONTAINER_NAME],
8009                              after[CONTAINER_ROWID]);
8010  if (rc)
8011    return rc;
8012
8013  if (strcasecmp(BeforeGroupName, AfterGroupName))
8014    {
8015      argv[L_NAME] = BeforeGroupName;
8016      argv[L_NAME + 1] = AfterGroupName;
8017      argv[L_ACTIVE + 1] = "1";
8018      argv[L_PUBLIC + 1] = "0";
8019      argv[L_HIDDEN + 1] = "0";
8020      argv[L_MAILLIST + 1] = "0";
8021      argv[L_GROUP + 1] = "1";
8022      argv[L_GID + 1] = UNIQUE_GID;
8023      argv[L_NFSGROUP + 1] = "0";
8024      argv[L_MAILMAN + 1] = "0";
8025      argv[L_MAILMAN_SERVER + 1] = "[NONE]";
8026      argv[L_DESC + 1] = "auto created container group";
8027      argv[L_ACE_TYPE + 1] = "USER";
8028      argv[L_MEMACE_TYPE + 1] = "USER";
8029      argv[L_ACE_NAME + 1] = "sms";
8030      argv[L_MEMACE_NAME + 1] = "sms";
8031     
8032      if (rc = mr_query("update_list", 16, argv, NULL, NULL))
8033        {
8034          com_err(whoami, 0,
8035                  "Unable to rename container group from %s to %s: %s",
8036                  BeforeGroupName, AfterGroupName, error_message(rc));
8037        }
8038    }
8039 
8040  return(rc);
8041}
8042
8043int Moira_container_group_delete(char **before)
8044{
8045  long rc = 0;
8046  char *argv[13];
8047  char GroupName[64];
8048  char ParentGroupName[64];
8049 
8050  memset(ParentGroupName, '\0', sizeof(ParentGroupName));
8051  Moira_getGroupName(before[CONTAINER_NAME], ParentGroupName, 1);
8052
8053  memset(GroupName, '\0', sizeof(GroupName));
8054
8055  if (strcmp(before[CONTAINER_GROUP_NAME], "[none]"))
8056    strcpy(GroupName, before[CONTAINER_GROUP_NAME]);
8057 
8058  if ((strlen(ParentGroupName) != 0) && (strlen(GroupName) != 0))
8059    {
8060      argv[0] = ParentGroupName;
8061      argv[1] = "LIST";
8062      argv[2] = GroupName;
8063
8064      if (rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL))
8065        {
8066          com_err(whoami, 0,
8067                  "Unable to delete container group %s from list: %s",
8068                  GroupName, ParentGroupName, error_message(rc));
8069        }
8070    }
8071 
8072  if (strlen(GroupName) != 0)
8073    {
8074      argv[0] = GroupName;
8075
8076      if (rc = mr_query("delete_list", 1, argv, NULL, NULL))
8077        {
8078          com_err(whoami, 0, "Unable to delete container group %s : %s",
8079                  GroupName, error_message(rc));
8080        }
8081    }
8082 
8083  return(rc);
8084}
8085
8086int Moira_groupname_create(char *GroupName, char *ContainerName,
8087                           char *ContainerRowID)
8088{
8089  char *ptr;
8090  char *ptr1;
8091  char temp[64];
8092  char newGroupName[64];
8093  char tempGroupName[64];
8094  char tempgname[64];
8095  char *argv[1];
8096  int  i;
8097  long rc;
8098
8099  strcpy(temp, ContainerName);
8100 
8101  ptr1 = strrchr(temp, '/');
8102
8103  if (ptr1 != NULL)
8104  {
8105    *ptr1 = '\0';
8106    ptr = ++ptr1;
8107    ptr1 = strrchr(temp, '/');
8108
8109    if (ptr1 != NULL)
8110    {
8111        sprintf(tempgname, "%s-%s", ++ptr1, ptr);
8112    }
8113    else
8114        strcpy(tempgname, ptr);
8115  }
8116  else
8117    strcpy(tempgname, temp);
8118
8119  if (strlen(tempgname) > 25)
8120    tempgname[25] ='\0';
8121
8122  sprintf(newGroupName, "cnt-%s", tempgname);
8123
8124  /* change everything to lower case */
8125  ptr = newGroupName;
8126
8127  while (*ptr)
8128    {
8129      if (isupper(*ptr))
8130        *ptr = tolower(*ptr);
8131
8132      if (*ptr == ' ')
8133        *ptr = '-';
8134
8135      ptr++;
8136    }
8137
8138  strcpy(tempGroupName, newGroupName);
8139  i = (int)'0';
8140
8141  /* append 0-9 then a-z if a duplicate is found */
8142  while(1)
8143    {
8144      argv[0] = newGroupName;
8145
8146      if (rc = mr_query("get_list_info", 1, argv, NULL, NULL))
8147        {
8148          if (rc == MR_NO_MATCH)
8149            break;
8150          com_err(whoami, 0, "Moira error while creating group name for "
8151                  "container %s : %s", ContainerName, error_message(rc));
8152          return rc;
8153        }
8154
8155      sprintf(newGroupName, "%s-%c", tempGroupName, i);
8156
8157      if (i == (int)'z')
8158        {
8159          com_err(whoami, 0, "Unable to find a unique group name for "
8160                  "container %s: too many duplicate container names",
8161                  ContainerName);
8162          return 1;
8163        }
8164
8165      if (i == '9')
8166        i = 'a';
8167      else
8168        i++;
8169    }
8170
8171  strcpy(GroupName, newGroupName);
8172  return(0);
8173}
8174
8175int Moira_setContainerGroup(char *origContainerName, char *GroupName)
8176{
8177  long rc;
8178  char *argv[3];
8179 
8180  argv[0] = origContainerName;
8181  argv[1] = GroupName;
8182 
8183  if ((rc = mr_query("set_container_list", 2, argv, NULL, NULL)))
8184    {
8185      com_err(whoami, 0,
8186              "Unable to set container group %s in container %s: %s",
8187              GroupName, origContainerName, error_message(rc));
8188    }
8189 
8190  return(0);
8191}
8192
8193int Moira_addGroupToParent(char *origContainerName, char *GroupName)
8194 {
8195   char ContainerName[64];
8196   char ParentGroupName[64];
8197   char *argv[3];
8198   long rc;
8199
8200   strcpy(ContainerName, origContainerName);
8201   
8202   Moira_getGroupName(ContainerName, ParentGroupName, 1);
8203
8204   /* top-level container */
8205   if (strlen(ParentGroupName) == 0)
8206     return(0);
8207   
8208   argv[0] = ParentGroupName;
8209   argv[1] = "LIST";
8210   argv[2] = GroupName;
8211
8212   if ((rc = mr_query("add_member_to_list", 3, argv, NULL, NULL)))
8213     {
8214       com_err(whoami, 0,
8215               "Unable to add container group %s to parent group %s: %s",
8216               GroupName, ParentGroupName, error_message(rc));
8217     }
8218   
8219   return(0);
8220 }
8221
8222int Moira_getContainerGroup(int ac, char **av, void *ptr)
8223{
8224  char **call_args;
8225 
8226  call_args = ptr;
8227  strcpy(call_args[0], av[1]);
8228
8229  return(0);
8230}
8231
8232int Moira_getGroupName(char *origContainerName, char *GroupName,
8233                       int ParentFlag)
8234{
8235  char ContainerName[64];
8236  char *argv[3];
8237  char *call_args[3];
8238  char *ptr;
8239  long rc;
8240
8241  strcpy(ContainerName, origContainerName);
8242
8243  if (ParentFlag)
8244    {
8245      ptr = strrchr(ContainerName, '/');
8246
8247      if (ptr != NULL)
8248        (*ptr) = '\0';
8249      else
8250        return(0);
8251    }
8252
8253  argv[0] = ContainerName;
8254  argv[1] = NULL;
8255  call_args[0] = GroupName;
8256  call_args[1] = NULL;
8257
8258  if (!(rc = mr_query("get_container_list", 1, argv, Moira_getContainerGroup,
8259                      call_args)))
8260    {
8261      if (strlen(GroupName) != 0)
8262        return(0);
8263    }
8264
8265  if (rc)
8266    com_err(whoami, 0, "Unable to get container group from container %s: %s",
8267            ContainerName, error_message(rc));
8268  else
8269    com_err(whoami, 0, "Unable to get container group from container %s",
8270            ContainerName);
8271 
8272  return(0);
8273}
8274
8275int Moira_process_machine_container_group(char *MachineName, char* GroupName,
8276                                          int DeleteMachine)
8277{
8278  char *argv[3];
8279  long rc;
8280 
8281  if (strcmp(GroupName, "[none]") == 0)
8282    return 0;
8283
8284  argv[0] = GroupName;
8285  argv[1] = "MACHINE";
8286  argv[2] = MachineName;
8287
8288  if (!DeleteMachine)
8289    rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
8290  else
8291    rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
8292
8293  if (rc)
8294    {
8295      com_err(whoami, 0, "Unable to add machine %s to container group%s: %s",
8296              MachineName, GroupName, error_message(rc));
8297    }
8298
8299  return(0);
8300}
8301
8302int GetMachineName(char *MachineName)
8303{
8304  char    *args[2];
8305  char    NewMachineName[1024];
8306  char    *szDot;
8307  int     rc = 0;
8308  int     i;
8309  DWORD   dwLen = 0;
8310  char    *call_args[2];
8311 
8312  // If the address happens to be in the top-level MIT domain, great!
8313  strcpy(NewMachineName, MachineName);
8314
8315  for (i = 0; i < (int)strlen(NewMachineName); i++)
8316    NewMachineName[i] = toupper(NewMachineName[i]);
8317
8318  szDot = strchr(NewMachineName,'.');
8319
8320  if ((szDot) && (!strcasecmp(szDot+1, DOMAIN_SUFFIX)))
8321    {
8322      return(0);
8323    }
8324 
8325  // If not, see if it has a Moira alias in the top-level MIT domain.
8326  memset(NewMachineName, '\0', sizeof(NewMachineName));
8327  args[0] = "*";
8328  args[1] = MachineName;
8329  call_args[0] = NewMachineName;
8330  call_args[1] = NULL;
8331
8332  if (rc = mr_query("get_hostalias", 2, args, ProcessMachineName, call_args))
8333    {
8334      com_err(whoami, 0, "Unable to resolve machine name %s : %s",
8335              MachineName, error_message(rc));
8336      strcpy(MachineName, "");
8337      return(0);
8338    }
8339 
8340  if (strlen(NewMachineName) != 0)
8341    strcpy(MachineName, NewMachineName);
8342  else
8343    strcpy(MachineName, "");
8344
8345  return(0);
8346}
8347
8348int ProcessMachineName(int ac, char **av, void *ptr)
8349{
8350  char    **call_args;
8351  char    MachineName[1024];
8352  char    *szDot;
8353  int     i;
8354 
8355  call_args = ptr;
8356
8357  if (strlen(call_args[0]) == 0)
8358    {
8359      strcpy(MachineName, av[0]);
8360
8361      for (i = 0; i < (int)strlen(MachineName); i++)
8362        MachineName[i] = toupper(MachineName[i]);
8363
8364      szDot = strchr(MachineName,'.');
8365
8366        if ((szDot) && (!strcasecmp(szDot+1,DOMAIN_SUFFIX)))
8367          {
8368            strcpy(call_args[0], MachineName);
8369          }
8370    }
8371
8372  return(0);
8373}
8374
8375void SwitchSFU(LDAPMod **mods, int *UseSFU30, int n)
8376{
8377  int i;
8378 
8379  if (*UseSFU30)
8380    {
8381      for (i = 0; i < n; i++)
8382        {
8383          if (!strcmp(mods[i]->mod_type, "msSFU30UidNumber"))
8384            mods[i]->mod_type = "uidNumber";
8385        }
8386
8387      (*UseSFU30) = 0;
8388    }
8389  else
8390    {
8391      for (i = 0; i < n; i++)
8392        {
8393          if (!strcmp(mods[i]->mod_type, "uidNumber"))
8394            mods[i]->mod_type = "msSFU30UidNumber";
8395        }
8396
8397      (*UseSFU30) = 1;
8398    }
8399}
8400
8401int SetHomeDirectory(LDAP *ldap_handle, char *user_name,
8402                     char *DistinguishedName,
8403                     char *WinHomeDir, char *WinProfileDir,
8404                     char **homedir_v, char **winProfile_v,
8405                     char **drives_v, char **apple_homedir_v, LDAPMod **mods,
8406                     int OpType, int n)
8407{
8408  char cWeight[3];
8409  char cPath[1024];
8410  char path[1024];
8411  char winPath[1024];
8412  char winProfile[1024];
8413  char homeDrive[8];
8414  char homedir[1024];
8415  char apple_homedir[1024];
8416  int  last_weight;
8417  int  i;
8418  int  rc;
8419  LDAPMod *DelMods[20];
8420  char *argv[3];
8421  char *save_argv[FS_END];
8422  char *fsgroup_save_argv[2];
8423
8424  memset(homeDrive, '\0', sizeof(homeDrive));
8425  memset(path, '\0', sizeof(path));
8426  memset(winPath, '\0', sizeof(winPath));
8427  memset(winProfile, '\0', sizeof(winProfile));
8428
8429  if(!ActiveDirectory)
8430    {
8431      if (rc = moira_connect())
8432        {
8433          critical_alert(whoami, "Ldap incremental",
8434                         "Error contacting Moira server : %s",
8435                         error_message(rc));
8436          return(n);
8437        }
8438     
8439      argv[0] = user_name;
8440
8441      if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info,
8442                          save_argv)))
8443        {
8444          if(!strcmp(save_argv[FS_TYPE], "FSGROUP") ||
8445             !strcmp(save_argv[FS_TYPE], "MUL"))
8446            {
8447       
8448              argv[0] = save_argv[FS_NAME];
8449              fsgCount = 0;
8450             
8451              if (!(rc = mr_query("get_fsgroup_members", 1, argv,
8452                                  save_fsgroup_info, fsgroup_save_argv)))
8453                {
8454                  if(fsgCount)
8455                    {
8456                      argv[0] = fsgroup_save_argv[0];
8457                     
8458                      if (!(rc = mr_query("get_filesys_by_label", 1, argv,
8459                                          save_query_info, save_argv)))
8460                        {
8461                          strcpy(path, save_argv[FS_PACK]);
8462                        }
8463                    }
8464                }
8465            }
8466          else
8467            {
8468              strcpy(path, save_argv[FS_PACK]);
8469            }
8470        }
8471     
8472      moira_disconnect();
8473
8474      if (strlen(path))
8475        {
8476          if (!strnicmp(path, AFS, strlen(AFS)))
8477            {
8478              sprintf(homedir, "%s", path);
8479              sprintf(apple_homedir, "%s/MacData", path);
8480              homedir_v[0] = homedir;
8481              apple_homedir_v[0] = apple_homedir;
8482              ADD_ATTR("homeDirectory", homedir_v, OpType);
8483              ADD_ATTR("apple-user-homeDirectory", apple_homedir_v,
8484                       OpType);
8485            }
8486        }
8487      else
8488        {
8489          homedir_v[0] = "NONE";
8490          apple_homedir_v[0] = "NONE";
8491          ADD_ATTR("homeDirectory", homedir_v, OpType);
8492          ADD_ATTR("apple-user-homeDirectory", apple_homedir_v,
8493                   OpType);
8494        }
8495
8496      return(n);
8497    }
8498 
8499  if ((!strcasecmp(WinHomeDir, "[afs]")) ||
8500      (!strcasecmp(WinProfileDir, "[afs]")))
8501    {
8502      if (rc = moira_connect())
8503        {
8504          critical_alert(whoami, "Ldap incremental",
8505                         "Error contacting Moira server : %s",
8506                         error_message(rc));
8507          return(n);
8508        }
8509     
8510      argv[0] = user_name;
8511
8512      if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info,
8513                          save_argv)))
8514        {
8515          if(!strcmp(save_argv[FS_TYPE], "FSGROUP") ||
8516             !strcmp(save_argv[FS_TYPE], "MUL"))
8517            {
8518       
8519              argv[0] = save_argv[FS_NAME];
8520              fsgCount = 0;
8521             
8522              if (!(rc = mr_query("get_fsgroup_members", 1, argv,
8523                                  save_fsgroup_info, fsgroup_save_argv)))
8524                {
8525                  if(fsgCount)
8526                    {
8527                      argv[0] = fsgroup_save_argv[0];
8528                     
8529                      if (!(rc = mr_query("get_filesys_by_label", 1, argv,
8530                                          save_query_info, save_argv)))
8531                        {
8532                          strcpy(path, save_argv[FS_PACK]);
8533                        }
8534                    }
8535                }
8536            }
8537          else
8538            {
8539              strcpy(path, save_argv[FS_PACK]);
8540            }
8541        }
8542     
8543      moira_disconnect();
8544
8545      if (strlen(path))
8546        {
8547          if (!strnicmp(path, AFS, strlen(AFS)))
8548            {
8549              AfsToWinAfs(path, winPath);
8550              strcpy(winProfile, winPath);
8551              strcat(winProfile, "\\.winprofile");
8552            }
8553        }
8554      else
8555        return(n);
8556    }
8557
8558    if ((!strcasecmp(WinHomeDir, "[dfs]")) ||
8559        (!strcasecmp(WinProfileDir, "[dfs]")))
8560    {
8561      sprintf(path, "\\\\%s\\dfs\\profiles\\%c\\%s", ldap_domain,
8562              user_name[0], user_name);
8563
8564      if (!strcasecmp(WinProfileDir, "[dfs]"))
8565        {
8566          strcpy(winProfile, path);
8567          strcat(winProfile, "\\.winprofile");
8568        }
8569
8570      if (!strcasecmp(WinHomeDir, "[dfs]"))
8571        strcpy(winPath, path);
8572    }
8573   
8574    if (!strcasecmp(WinHomeDir, "[local]"))
8575      memset(winPath, '\0', sizeof(winPath));
8576    else if (!strcasecmp(WinHomeDir, "[afs]") ||
8577             !strcasecmp(WinHomeDir, "[dfs]"))
8578      {
8579        strcpy(homeDrive, "H:");
8580      }
8581    else
8582      {
8583        strcpy(winPath, WinHomeDir);
8584        if (!strncmp(WinHomeDir, "\\\\", 2))
8585          {
8586            strcpy(homeDrive, "H:");
8587          }       
8588      }
8589   
8590    // nothing needs to be done if WinProfileDir is [afs].
8591    if (!strcasecmp(WinProfileDir, "[local]"))
8592      memset(winProfile, '\0', sizeof(winProfile));
8593    else if (strcasecmp(WinProfileDir, "[afs]") &&
8594             strcasecmp(WinProfileDir, "[dfs]"))
8595      {
8596        strcpy(winProfile, WinProfileDir);
8597      }
8598   
8599    if (strlen(winProfile) != 0)
8600      {
8601        if (winProfile[strlen(winProfile) - 1] == '\\')
8602          winProfile[strlen(winProfile) - 1] = '\0';
8603      }
8604
8605    if (strlen(winPath) != 0)
8606      {
8607        if (winPath[strlen(winPath) - 1] == '\\')
8608          winPath[strlen(winPath) - 1] = '\0';
8609      }
8610   
8611    if ((winProfile[1] == ':') && (strlen(winProfile) == 2))
8612      strcat(winProfile, "\\");
8613
8614    if ((winPath[1] == ':') && (strlen(winPath) == 2))
8615      strcat(winPath, "\\");
8616   
8617    if (strlen(winPath) == 0)
8618      {
8619        if (OpType == LDAP_MOD_REPLACE)
8620          {
8621            i = 0;
8622            DEL_ATTR("homeDirectory", LDAP_MOD_DELETE);
8623            DelMods[i] = NULL;
8624            //unset homeDirectory attribute for user.
8625            rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8626            free(DelMods[0]);
8627          }
8628      }
8629    else
8630      {
8631        homedir_v[0] = strdup(winPath);
8632        ADD_ATTR("homeDirectory", homedir_v, OpType);
8633      }
8634   
8635    if (strlen(winProfile) == 0)
8636      {
8637        if (OpType == LDAP_MOD_REPLACE)
8638          {
8639            i = 0;
8640            DEL_ATTR("profilePath", LDAP_MOD_DELETE);
8641            DelMods[i] = NULL;
8642            //unset profilePate attribute for user.
8643            rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8644            free(DelMods[0]);
8645          }
8646      }
8647    else
8648      {
8649        winProfile_v[0] = strdup(winProfile);
8650        ADD_ATTR("profilePath", winProfile_v, OpType);
8651      }
8652   
8653    if (strlen(homeDrive) == 0)
8654      {
8655        if (OpType == LDAP_MOD_REPLACE)
8656          {
8657            i = 0;
8658            DEL_ATTR("homeDrive", LDAP_MOD_DELETE);
8659            DelMods[i] = NULL;
8660            //unset homeDrive attribute for user
8661            rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8662            free(DelMods[0]);
8663          }
8664      }
8665    else
8666      {
8667        drives_v[0] = strdup(homeDrive);
8668        ADD_ATTR("homeDrive", drives_v, OpType);
8669      }
8670
8671    return(n);
8672}
8673
8674int attribute_update(LDAP *ldap_handle, char *distinguished_name,
8675                     char *attribute_value, char *attribute, char *user_name)
8676{
8677  char      *mod_v[] = {NULL, NULL};
8678  LDAPMod   *DelMods[20];
8679  LDAPMod   *mods[20];
8680  int       n;
8681  int       i;
8682  int       rc;
8683 
8684  if (strlen(attribute_value) == 0)
8685    {
8686      i = 0;
8687      DEL_ATTR(attribute, LDAP_MOD_DELETE);
8688      DelMods[i] = NULL;
8689      rc = ldap_modify_s(ldap_handle, distinguished_name, DelMods);
8690      free(DelMods[0]);
8691    }
8692  else
8693    {
8694      n = 0;
8695      mod_v[0] = attribute_value;
8696      ADD_ATTR(attribute, mod_v, LDAP_MOD_REPLACE);
8697      mods[n] = NULL;
8698
8699      if ((rc = ldap_modify_s(ldap_handle, distinguished_name,
8700                              mods)) != LDAP_SUCCESS)
8701        {
8702          free(mods[0]);
8703          n = 0;
8704          mod_v[0] = attribute_value;
8705          ADD_ATTR(attribute, mod_v, LDAP_MOD_ADD);
8706          mods[n] = NULL;
8707
8708          if ((rc = ldap_modify_s(ldap_handle, distinguished_name,
8709                                  mods)) != LDAP_SUCCESS)
8710            {
8711              com_err(whoami, 0, "Unable to change the %s attribute for %s "
8712                      "in the directory : %s",
8713                      attribute, user_name, ldap_err2string(rc));
8714            }
8715        }
8716
8717      free(mods[0]);
8718    }
8719 
8720  return(rc);
8721}
8722
8723void StringTrim(char *StringToTrim)
8724{
8725  char *t, *s;
8726  char *save;
8727
8728  save = strdup(StringToTrim);
8729
8730  s = save;
8731
8732  while (isspace(*s))
8733    s++;
8734
8735  /* skip to end of string */
8736  if (*s == '\0')
8737    {
8738      if (*save)
8739        *save = '\0';
8740      strcpy(StringToTrim, save);
8741      return;
8742    }
8743 
8744  for (t = s; *t; t++)
8745    continue;
8746
8747  while (t > s)
8748    {
8749      --t;
8750      if (!isspace(*t))
8751        {
8752          t++;
8753          break;
8754        }
8755    }
8756
8757  if (*t)
8758    *t = '\0';
8759 
8760  strcpy(StringToTrim, s);
8761  return;
8762}
8763
8764int ReadConfigFile(char *DomainName)
8765{
8766    int     Count;
8767    int     i;
8768    int     k;
8769    char    temp[256];
8770    char    temp1[256];
8771    FILE    *fptr;
8772
8773    Count = 0;
8774
8775    sprintf(temp, "%s%s.cfg", CFG_PATH, DomainName);
8776
8777    if ((fptr = fopen(temp, "r")) != NULL)
8778      {
8779        while (fgets(temp, sizeof(temp), fptr) != 0)
8780          {
8781            for (i = 0; i < (int)strlen(temp); i++)
8782              temp[i] = toupper(temp[i]);
8783
8784            if (temp[strlen(temp) - 1] == '\n')
8785              temp[strlen(temp) - 1] = '\0';
8786
8787            StringTrim(temp);
8788
8789            if (strlen(temp) == 0)
8790              continue;
8791
8792            if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
8793              {
8794                if (strlen(temp) > (strlen(DOMAIN)))
8795                  {
8796                    strcpy(ldap_domain, &temp[strlen(DOMAIN)]);
8797                    StringTrim(ldap_domain);
8798                  }
8799              }
8800            else if (!strncmp(temp, REALM, strlen(REALM)))
8801              {
8802                if (strlen(temp) > (strlen(REALM)))
8803                  {
8804                    strcpy(ldap_realm, &temp[strlen(REALM)]);
8805                    StringTrim(ldap_realm);
8806                  }
8807              }
8808            else if (!strncmp(temp, PORT, strlen(PORT)))
8809              {
8810                if (strlen(temp) > (strlen(PORT)))
8811                  {
8812                    strcpy(ldap_port, &temp[strlen(PORT)]);
8813                    StringTrim(ldap_port);
8814                  }
8815              }
8816            else if (!strncmp(temp, PRINCIPALNAME, strlen(PRINCIPALNAME)))
8817              {
8818                if (strlen(temp) > (strlen(PRINCIPALNAME)))
8819                  {
8820                    strcpy(PrincipalName, &temp[strlen(PRINCIPALNAME)]);
8821                    StringTrim(PrincipalName);
8822                  }
8823              }
8824            else if (!strncmp(temp, SERVER, strlen(SERVER)))
8825              {
8826                if (strlen(temp) > (strlen(SERVER)))
8827                  {
8828                    ServerList[Count] = calloc(1, 256);
8829                    strcpy(ServerList[Count], &temp[strlen(SERVER)]);
8830                    StringTrim(ServerList[Count]);
8831                    ++Count;
8832                  }
8833              }
8834            else if (!strncmp(temp, MSSFU, strlen(MSSFU)))
8835              {
8836                if (strlen(temp) > (strlen(MSSFU)))
8837                  {
8838                    strcpy(temp1, &temp[strlen(MSSFU)]);
8839                    StringTrim(temp1);
8840                    if (!strcmp(temp1, SFUTYPE))
8841                      UseSFU30 = 1;
8842                  }
8843              }
8844            else if (!strncmp(temp, GROUP_SUFFIX, strlen(GROUP_SUFFIX)))
8845              {
8846                if (strlen(temp) > (strlen(GROUP_SUFFIX)))
8847                  {
8848                    strcpy(temp1, &temp[strlen(GROUP_SUFFIX)]);
8849                    StringTrim(temp1);
8850                    if (!strcasecmp(temp1, "NO"))
8851                      {
8852                        UseGroupSuffix = 0;
8853                        memset(group_suffix, '\0', sizeof(group_suffix));
8854                      }
8855                  }
8856              }
8857            else if (!strncmp(temp, GROUP_TYPE, strlen(GROUP_TYPE)))
8858              {
8859                if (strlen(temp) > (strlen(GROUP_TYPE)))
8860                  {
8861                    strcpy(temp1, &temp[strlen(GROUP_TYPE)]);
8862                    StringTrim(temp1);
8863                    if (!strcasecmp(temp1, "UNIVERSAL"))
8864                      UseGroupUniversal = 1;
8865                  }
8866              }
8867            else if (!strncmp(temp, SET_GROUP_ACE, strlen(SET_GROUP_ACE)))
8868              {
8869                if (strlen(temp) > (strlen(SET_GROUP_ACE)))
8870                  {
8871                    strcpy(temp1, &temp[strlen(SET_GROUP_ACE)]);
8872                    StringTrim(temp1);
8873                    if (!strcasecmp(temp1, "NO"))
8874                      SetGroupAce = 0;
8875                  }
8876              }
8877            else if (!strncmp(temp, SET_PASSWORD, strlen(SET_PASSWORD)))
8878              {
8879                if (strlen(temp) > (strlen(SET_PASSWORD)))
8880                  {
8881                    strcpy(temp1, &temp[strlen(SET_PASSWORD)]);
8882                    StringTrim(temp1);
8883                    if (!strcasecmp(temp1, "NO"))
8884                      SetPassword = 0;
8885                  }
8886              }
8887            else if (!strncmp(temp, EXCHANGE, strlen(EXCHANGE)))
8888              {
8889                if (strlen(temp) > (strlen(EXCHANGE)))
8890                  {
8891                    strcpy(temp1, &temp[strlen(EXCHANGE)]);
8892                    StringTrim(temp1);
8893                    if (!strcasecmp(temp1, "YES"))
8894                      Exchange = 1;
8895                  }
8896              }
8897            else if (!strncmp(temp, PROCESS_MACHINE_CONTAINER,
8898                              strlen(PROCESS_MACHINE_CONTAINER)))
8899              {
8900                if (strlen(temp) > (strlen(PROCESS_MACHINE_CONTAINER)))
8901                  {
8902                    strcpy(temp1, &temp[strlen(PROCESS_MACHINE_CONTAINER)]);
8903                    StringTrim(temp1);
8904                    if (!strcasecmp(temp1, "NO"))
8905                      ProcessMachineContainer = 0;
8906                  }
8907              }
8908            else if (!strncmp(temp, ACTIVE_DIRECTORY,
8909                              strlen(ACTIVE_DIRECTORY)))
8910              {
8911                if (strlen(temp) > (strlen(ACTIVE_DIRECTORY)))
8912                  {
8913                    strcpy(temp1, &temp[strlen(ACTIVE_DIRECTORY)]);
8914                    StringTrim(temp1);
8915                    if (!strcasecmp(temp1, "NO"))
8916                      ActiveDirectory = 0;
8917                  }
8918              }
8919            else if (!strncmp(temp, GROUP_POPULATE_MEMBERS,
8920                              strlen(GROUP_POPULATE_MEMBERS)))
8921              {
8922                if (strlen(temp) > (strlen(GROUP_POPULATE_MEMBERS)))
8923                  {
8924                    strcpy(temp1, &temp[strlen(GROUP_POPULATE_MEMBERS)]);
8925                    StringTrim(temp1);
8926                    if (!strcasecmp(temp1, "DELETE"))
8927                      {
8928                        GroupPopulateDelete = 1;
8929                      }
8930                  }
8931              }
8932            else if (!strncmp(temp, MAX_MEMBERS, strlen(MAX_MEMBERS)))
8933              {
8934                if (strlen(temp) > (strlen(MAX_MEMBERS)))
8935                  {
8936                    strcpy(temp1, &temp[strlen(MAX_MEMBERS)]);
8937                    StringTrim(temp1);
8938                    max_group_members = atoi(temp1);
8939                  }
8940              }
8941            else
8942              {
8943                if (strlen(ldap_domain) != 0)
8944                  {
8945                    memset(ldap_domain, '\0', sizeof(ldap_domain));
8946                    break;
8947                  }
8948
8949                if (strlen(temp) != 0)
8950                  strcpy(ldap_domain, temp);
8951              }
8952          }
8953        fclose(fptr);
8954      }
8955   
8956    if (strlen(ldap_domain) == 0)
8957      {
8958      strcpy(ldap_domain, DomainName);
8959      }
8960
8961    if (Count == 0)
8962        return(0);
8963
8964    for (i = 0; i < Count; i++)
8965      {
8966        if (ServerList[i] != 0)
8967          {
8968            for (k = 0; k < (int)strlen(ServerList[i]); k++)
8969              ServerList[i][k] = toupper(ServerList[i][k]);
8970          }
8971      }
8972   
8973    return(0);
8974}
8975
8976int ReadDomainList()
8977{
8978  int     Count;
8979  int     i;
8980  char    temp[128];
8981  char    temp1[128];
8982  FILE    *fptr;
8983  unsigned char c[11];
8984  unsigned char stuff[256];
8985  int     rc;
8986  int     ok;
8987
8988  Count = 0;
8989  sprintf(temp, "%s%s", CFG_PATH, WINADCFG);
8990
8991  if ((fptr = fopen(temp, "r")) != NULL)
8992    {
8993      while (fgets(temp, sizeof(temp), fptr) != 0)
8994        {
8995          for (i = 0; i < (int)strlen(temp); i++)
8996            temp[i] = toupper(temp[i]);
8997
8998          if (temp[strlen(temp) - 1] == '\n')
8999            temp[strlen(temp) - 1] = '\0';
9000
9001          StringTrim(temp);
9002
9003          if (strlen(temp) == 0)
9004            continue;
9005
9006          if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
9007            {
9008              if (strlen(temp) > (strlen(DOMAIN)))
9009                {
9010                  strcpy(temp1, &temp[strlen(DOMAIN)]);
9011                  StringTrim(temp1);
9012                  strcpy(temp, temp1);
9013                }
9014            }
9015         
9016          strcpy(DomainNames[Count], temp);
9017          StringTrim(DomainNames[Count]);
9018          ++Count;
9019        }
9020
9021      fclose(fptr);
9022    }
9023
9024  if (Count == 0)
9025    {
9026      critical_alert(whoami, "incremental", "%s", "ldap.incr cannot run due to a "
9027                     "configuration error in ldap.cfg");
9028      return(1);
9029    }
9030 
9031  return(0);
9032}
9033
9034int email_isvalid(const char *address) {
9035  int        count = 0;
9036  const char *c, *domain;
9037  static char *rfc822_specials = "()<>@,;:\\\"[]";
9038
9039  if(address[strlen(address) - 1] == '.')
9040    return 0;
9041   
9042  /* first we validate the name portion (name@domain) */
9043  for (c = address;  *c;  c++) {
9044    if (*c == '\"' && (c == address || *(c - 1) == '.' || *(c - 1) ==
9045                       '\"')) {
9046      while (*++c) {
9047        if (*c == '\"')
9048          break;
9049        if (*c == '\\' && (*++c == ' '))
9050          continue;
9051        if (*c <= ' ' || *c >= 127)
9052          return 0;
9053      }
9054
9055      if (!*c++)
9056        return 0;
9057      if (*c == '@')
9058        break;
9059      if (*c != '.')
9060        return 0;
9061      continue;
9062    }
9063
9064    if (*c == '@')
9065      break;
9066    if (*c <= ' ' || *c >= 127)
9067      return 0;
9068    if (strchr(rfc822_specials, *c))
9069      return 0;
9070  }
9071
9072  if (c == address || *(c - 1) == '.')
9073    return 0;
9074
9075  /* next we validate the domain portion (name@domain) */
9076  if (!*(domain = ++c)) return 0;
9077  do {
9078    if (*c == '.') {
9079      if (c == domain || *(c - 1) == '.')
9080        return 0;
9081      count++;
9082    }
9083    if (*c <= ' ' || *c >= 127)
9084      return 0;
9085    if (strchr(rfc822_specials, *c))
9086      return 0;
9087  } while (*++c);
9088
9089  return (count >= 1);
9090}
9091
9092int find_homeMDB(LDAP *ldap_handle, char *dn_path, char **homeMDB,
9093             char **homeServerName)
9094{
9095  LK_ENTRY *group_base;
9096  LK_ENTRY *sub_group_base;
9097  LK_ENTRY *gPtr;
9098  LK_ENTRY *sub_gPtr;
9099  int      group_count;
9100  int      sub_group_count;
9101  char     filter[1024];
9102  char     sub_filter[1024];
9103  char     search_path[1024];
9104  char     range[1024];
9105  char     *attr_array[3];
9106  char     *s;
9107  int      homeMDB_count = -1;
9108  int      rc;
9109  int      i;
9110  int      mdbbl_count;
9111  int      rangeStep = 1500;
9112  int      rangeLow = 0;
9113  int      rangeHigh = rangeLow + (rangeStep - 1);
9114  int      isLast = 0;
9115
9116  /* Grumble..... microsoft not making it searchable from the root *grr* */
9117
9118  memset(filter, '\0', sizeof(filter));
9119  memset(search_path, '\0', sizeof(search_path));
9120 
9121  sprintf(filter, "(objectClass=msExchMDB)");
9122  sprintf(search_path, "CN=Configuration,%s", dn_path);
9123  attr_array[0] = "distinguishedName";
9124  attr_array[1] = NULL;
9125 
9126  group_base = NULL;
9127  group_count = 0;
9128 
9129  if ((rc = linklist_build(ldap_handle, search_path, filter, attr_array,
9130                           &group_base, &group_count,
9131                           LDAP_SCOPE_SUBTREE)) != 0)
9132    {
9133      com_err(whoami, 0, "Unable to find msExchMDB %s",
9134              ldap_err2string(rc));
9135      return(rc);
9136    }
9137 
9138  if (group_count)
9139    {
9140      gPtr = group_base;
9141     
9142      while(gPtr) {
9143        if (((s = strstr(gPtr->dn, "Public")) != (char *) NULL) ||
9144            ((s = strstr(gPtr->dn, "Recover")) != (char *) NULL) ||
9145            ((s = strstr(gPtr->dn, "Reserve")) != (char *) NULL))
9146          {
9147            gPtr = gPtr->next;
9148            continue;
9149          }
9150
9151        /*
9152         * Due to limits in active directory we need to use the LDAP
9153         * range semantics to query and return all the values in
9154         * large lists, we will stop increasing the range when
9155         * the result count is 0.
9156         */
9157
9158        i = 0; 
9159        mdbbl_count = 0;
9160
9161        for(;;)
9162          {
9163            memset(sub_filter, '\0', sizeof(sub_filter));
9164            memset(range, '\0', sizeof(range));
9165            sprintf(sub_filter, "(objectClass=msExchMDB)");
9166
9167            if(isLast)
9168              sprintf(range, "homeMDBBL;Range=%d-*", rangeLow);
9169            else
9170              sprintf(range, "homeMDBBL;Range=%d-%d", rangeLow, rangeHigh);
9171
9172            attr_array[0] = range;
9173            attr_array[1] = NULL;
9174           
9175            sub_group_base = NULL;
9176            sub_group_count = 0;
9177           
9178            if ((rc = linklist_build(ldap_handle, gPtr->dn, sub_filter,
9179                                     attr_array, &sub_group_base,
9180                                     &sub_group_count,
9181                                     LDAP_SCOPE_SUBTREE)) != 0)
9182              {
9183                com_err(whoami, 0, "Unable to find homeMDBBL %s",
9184                        ldap_err2string(rc));
9185                return(rc);
9186              }
9187
9188            if(!sub_group_count)
9189              {
9190                if(isLast)
9191                  {
9192                    isLast = 0;
9193                    rangeLow = 0;
9194                    rangeHigh = rangeLow + (rangeStep - 1);
9195                    break;
9196                  }
9197                else
9198                  isLast++;
9199              }
9200
9201            mdbbl_count += sub_group_count;
9202            rangeLow = rangeHigh + 1;
9203            rangeHigh = rangeLow + (rangeStep - 1);
9204          }
9205
9206        /* First time through, need to initialize or update the least used */
9207       
9208        com_err(whoami, 0, "Mail store %s, count %d", gPtr->dn,
9209                mdbbl_count);
9210
9211        if(mdbbl_count < homeMDB_count || homeMDB_count == -1)
9212          {
9213            homeMDB_count = mdbbl_count;
9214            *homeMDB = strdup(gPtr->dn);
9215          }
9216
9217        gPtr = gPtr->next;
9218        linklist_free(sub_group_base);
9219      }
9220    }
9221
9222  linklist_free(group_base);
9223 
9224  /*
9225   * Ok found the server least allocated need to now query to get its
9226   * msExchHomeServerName so we can set it as a user attribute
9227   */
9228 
9229  attr_array[0] = "legacyExchangeDN";
9230  attr_array[1] = NULL;
9231 
9232  group_count = 0;
9233  group_base = NULL;
9234 
9235  if ((rc = linklist_build(ldap_handle, *homeMDB, filter,
9236                           attr_array, &group_base,
9237                           &group_count,
9238                           LDAP_SCOPE_SUBTREE)) != 0)
9239    {
9240      com_err(whoami, 0, "Unable to find msExchHomeServerName %s",
9241              ldap_err2string(rc));
9242      return(rc);
9243    } 
9244 
9245  if(group_count)
9246    {
9247      *homeServerName = strdup(group_base->value);
9248      if((s = strrchr(*homeServerName, '/')) != (char *) NULL)
9249        {
9250          *s = '\0';
9251        }
9252    }
9253
9254  linklist_free(group_base);
9255 
9256  return(rc);
9257}
9258     
9259char *lowercase(char *s)
9260{
9261  char *p;
9262
9263  for (p = s; *p; p++)
9264    {
9265      if (isupper(*p))
9266        *p = tolower(*p);
9267    }
9268  return s;
9269}
9270
9271char *uppercase(char *s)
9272{
9273  char *p;
9274
9275  for (p = s; *p; p++)
9276    {
9277      if (islower(*p))
9278        *p = toupper(*p);
9279    }
9280  return s;
9281}
9282
9283char *escape_string(char *s)
9284{
9285  char *p, *q;
9286  char string[1024];
9287  char temp[1024];
9288  int i = 0;
9289  int spaces = 0;
9290
9291  if(ActiveDirectory) {
9292    return strdup(s);
9293  }
9294
9295  memset(string, '\0', sizeof(string));
9296
9297  q = s;
9298
9299  /* Escape any special characters */
9300
9301  for(; *q != '\0'; q++) {
9302    if(*q == ',')
9303      string[i++] = '\\';
9304    if(*q == '+')
9305      string[i++] = '\\';
9306    if(*q == '"')
9307      string[i++] = '\\';
9308    if(*q == '\\')
9309      string[i++] = '\\';
9310    if(*q == '<')
9311      string[i++] = '\\';
9312    if(*q == '>')
9313      string[i++] = '\\';
9314    if(*q == ';')
9315      string[i++] = '\\';
9316    if(*q == '#')
9317      string[i++] = '\\';
9318    if(*q == '=')
9319      string[i++] = '\\';
9320
9321    string[i++] = *q;
9322  }
9323
9324  return strdup(string);
9325}
9326
9327int save_query_info(int argc, char **argv, void *hint)
9328{
9329  int i;
9330  char **nargv = hint;
9331
9332  for(i = 0; i < argc; i++)
9333    nargv[i] = strdup(argv[i]);
9334
9335  return MR_CONT;
9336}
9337
9338int save_fsgroup_info(int argc, char **argv, void *hint)
9339{
9340  int i;
9341  char **nargv = hint;
9342
9343  if(!fsgCount)
9344    {
9345      for(i = 0; i < argc; i++)
9346        nargv[i] = strdup(argv[i]);
9347
9348      fsgCount++;
9349    }
9350
9351  return MR_CONT;
9352}
9353
9354int contains_member(LDAP *ldap_handle, char *dn_path, char *group_name,
9355                    char *UserOu, char *user_name)
9356{
9357  char         search_filter[1024];
9358  char         *attr_array[3];
9359  LK_ENTRY     *group_base;
9360  int          group_count;
9361  int          rc;
9362  char         temp[256];
9363
9364  if(ActiveDirectory)
9365    {
9366      sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
9367    }
9368  else
9369    {
9370      if(!strcmp(UserOu, user_ou))
9371        sprintf(temp, "uid=%s,%s,%s", user_name, UserOu, dn_path);
9372      else
9373        sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
9374    }
9375
9376  group_base = NULL;
9377  group_count = 0;
9378 
9379  sprintf(search_filter, "(&(objectClass=group)(cn=%s)(member=%s))",
9380          group_name, temp);
9381
9382  attr_array[0] = "mitMoiraId";
9383  attr_array[1] = NULL;
9384
9385  if ((rc = linklist_build(ldap_handle, dn_path, search_filter,
9386                           attr_array, &group_base, &group_count,
9387                           LDAP_SCOPE_SUBTREE)) != 0)
9388    {
9389      com_err(whoami, 0, "Unable to check group %s for membership of %s : %s",
9390              group_name, user_name, ldap_err2string(rc));
9391      return(-1);
9392    }
9393         
9394  if (group_count)
9395    {
9396      rc = 1;
9397    }
9398  else
9399    {
9400      rc = 0;
9401    }
9402
9403  linklist_free(group_base);
9404  group_count = 0;
9405  group_base = NULL;
9406
9407  return(rc);
9408}
9409
9410static int sasl_flags = LDAP_SASL_QUIET;
9411static char *sasl_mech = "GSSAPI";
9412
9413/* warning! - the following requires intimate knowledge of sasl.h */
9414static char *default_values[] = {
9415  "", /* SASL_CB_USER         0x4001 */
9416  "", /* SASL_CB_AUTHNAME     0x4002 */
9417  "", /* SASL_CB_LANGUAGE     0x4003 */ /* not used */
9418  "", /* SASL_CB_PASS         0x4004 */
9419  "", /* SASL_CB_ECHOPROMPT   0x4005 */
9420  "", /* SASL_CB_NOECHOPROMPT   0x4005 */
9421  "", /* SASL_CB_CNONCE       0x4007 */
9422  ""  /* SASL_CB_GETREALM     0x4008 */
9423};
9424
9425/* this is so we can use SASL_CB_USER etc. to index into default_values */
9426#define VALIDVAL(n) ((n >= SASL_CB_USER) && (n <= SASL_CB_GETREALM))
9427#define VAL(n) default_values[n-0x4001]
9428
9429static int example_sasl_interact( LDAP *ld, unsigned flags, void *defaults, void *prompts ) {
9430  sasl_interact_t         *interact = NULL;
9431  int                     rc;
9432
9433  if (prompts == NULL) {
9434    return (LDAP_PARAM_ERROR);
9435  }
9436
9437  for (interact = prompts; interact->id != SASL_CB_LIST_END; interact++) {
9438    if (VALIDVAL(interact->id)) {
9439      interact->result = VAL(interact->id);
9440      interact->len = strlen((char *)interact->result);
9441    }
9442  }
9443  return (LDAP_SUCCESS);
9444}
9445
9446int ad_connect(LDAP **ldap_handle, char *ldap_domain, char *dn_path,
9447               char *Win2kPassword, char *Win2kUser, char *default_server,
9448               int connect_to_kdc, char **ServerList, char *ldap_realm,
9449               char *ldap_port)
9450{
9451  int         i;
9452  int         k;
9453  int         Count;
9454  char        *server_name[MAX_SERVER_NAMES];
9455  static char temp[128];
9456  ULONG       version = LDAP_VERSION3;
9457  ULONG       rc;
9458  int         Max_wait_time = 1000;
9459  int         Max_size_limit = LDAP_NO_LIMIT;
9460  LDAPControl **ctrls = NULL;
9461
9462  if (strlen(ldap_domain) == 0)
9463    return(1);
9464
9465  if (strlen(ldap_port) == 0)
9466    return(1);
9467
9468  convert_domain_to_dn(ldap_domain, dn_path);
9469  if (strlen(dn_path) == 0)
9470    return(1);
9471
9472  Count = 0;
9473  while (ServerList[Count] != NULL)
9474    ++Count;
9475
9476  if ((Count == 0) && (connect_to_kdc))
9477    return(1);
9478
9479  for (i = 0; i < Count; i++)
9480    {
9481      if (ServerList[i] == NULL)
9482        continue;
9483
9484      if (((*ldap_handle) = ldap_init(ServerList[i], atoi(ldap_port))) != NULL)
9485        {
9486          rc = ldap_set_option((*ldap_handle), LDAP_OPT_PROTOCOL_VERSION,
9487                               &version);
9488          rc = ldap_set_option((*ldap_handle), LDAP_OPT_TIMELIMIT,
9489                               (void *)&Max_wait_time);
9490          rc = ldap_set_option((*ldap_handle), LDAP_OPT_SIZELIMIT,
9491                               (void *)&Max_size_limit);
9492          rc = ldap_set_option((*ldap_handle), LDAP_OPT_REFERRALS,
9493                               LDAP_OPT_OFF);
9494
9495          rc = ldap_sasl_interactive_bind_ext_s((*ldap_handle), "", sasl_mech,
9496                                                 NULL, NULL, sasl_flags,
9497                                                 example_sasl_interact,
9498                                                 NULL, &ctrls);
9499
9500         
9501          if (rc == LDAP_SUCCESS)
9502            {
9503              if (connect_to_kdc)
9504                {
9505                  if (!ad_server_connect(ServerList[i], ldap_domain))
9506                    {
9507                      printf("ad_server_connect failed\n");
9508                      ldap_unbind_s((*ldap_handle));
9509                      (*ldap_handle) = NULL;
9510                      continue;
9511                    }
9512                }
9513              if (strlen(default_server) == 0)
9514                strcpy(default_server, ServerList[i]);
9515              strcpy(connected_server, ServerList[i]);
9516              break;
9517            }
9518          else
9519            {
9520              (*ldap_handle) = NULL;
9521            }
9522        }
9523    }
9524  if ((*ldap_handle) == NULL)
9525    return(1);
9526  return(0);
9527}
9528
9529int convert_domain_to_dn(char *domain, char *dnp)
9530{
9531  char    *fp;
9532  char    *dp;
9533  char    dn[512];
9534
9535  memset(dn, '\0', sizeof(dn));
9536  strcpy(dn, "dc=");
9537  dp = dn+3;
9538  for (fp = domain; *fp; fp++)
9539    {
9540      if (*fp == '.')
9541        {
9542          strcpy(dp, ",dc=");
9543          dp += 4;
9544        }
9545      else
9546        *dp++ = *fp;
9547    }
9548
9549  strcpy(dnp, dn);
9550  return 0;
9551}
9552
9553void ad_kdc_disconnect()
9554{
9555
9556  if (auth_context != NULL)
9557    {
9558      krb5_auth_con_free(context, auth_context);
9559      if (ap_req.data != NULL)
9560        free(ap_req.data);
9561      krb5_free_cred_contents(context, &creds);
9562      if (credsp != NULL)
9563        krb5_free_creds(context, credsp);
9564    }
9565  credsp = NULL;
9566  auth_context = NULL;
9567  if (context != NULL)
9568    {
9569      if (ccache)
9570        krb5_cc_close(context, ccache);
9571      krb5_free_context(context);
9572    }
9573  close(kdc_socket);
9574
9575}
Note: See TracBrowser for help on using the repository browser.