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

Revision 24447, 254.4 KB checked in by broder, 14 years ago (diff)
In moira: * New SVN snapshot.
  • Property svn:executable set to *
Line 
1/* $HeadURL: svn+ssh://svn.mit.edu/moira/trunk/moira/incremental/ldap/winad.c $ $Id: winad.c 3992 2010-03-15 02:52:24Z 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 *homeMDB_v[] = {NULL, NULL};
4137  char *homeServerName_v[] = {NULL, NULL};
4138  char *query_base_dn_v[] = {NULL, NULL};
4139  char *mail_nickname_v[] = {NULL, NULL};
4140  char *mdbUseDefaults_v[] = {NULL, NULL};
4141  char userAccountControlStr[80];
4142  int  n;
4143  int  rc;
4144  int  i;
4145  int  OldUseSFU30;
4146  u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD |
4147    UF_PASSWD_CANT_CHANGE;
4148  char filter[128];
4149  char *attr_array[3];
4150  char temp[1024];
4151  char mail[256];
4152  char filesys_name[256];
4153  char contact_mail[256];
4154  char filter_exp[1024];
4155  char search_path[512];
4156  char TemplateDn[512];
4157  char TemplateSamName[128];
4158  char alt_recipient[256];
4159  char principal[256];
4160  char status[256];
4161  char query_base_dn[256];
4162  char acBERBuf[N_SD_BER_BYTES];
4163  LDAPControl sControl = {"1.2.840.113556.1.4.801",
4164                          { N_SD_BER_BYTES, acBERBuf },
4165                          TRUE};
4166  LDAPControl *apsServerControls[] = {&sControl, NULL};
4167  LDAPMessage *psMsg;
4168  LDAP_BERVAL   **ppsValues;
4169  ULONG dwInfo;
4170  char *argv[3];
4171  char *homeMDB;
4172  char *homeServerName;
4173  char *save_argv[7];
4174  char search_string[256];
4175  char *p, *q;
4176  char *mail_routing_v[] = {NULL, NULL};
4177  char *mail_alternate_v[] = {NULL, NULL};
4178  char *mit_moira_imap_address_v[] = {NULL, NULL};
4179  char *deliver_and_redirect_v[] = {NULL, NULL};
4180  char *c;
4181
4182  dwInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
4183    DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
4184  BEREncodeSecurityBits(dwInfo, acBERBuf);
4185
4186  if (!check_string(user_name))
4187    {
4188      com_err(whoami, 0, "Unable to process invalid LDAP user name %s",
4189              user_name);
4190      return(AD_INVALID_NAME);
4191    }
4192 
4193  memset(contact_mail, '\0', sizeof(contact_mail));
4194
4195  if(Exchange)
4196    sprintf(contact_mail, "%s@exchange-forwarding.mit.edu", user_name);
4197  else
4198    sprintf(contact_mail, "%s@mit.edu", user_name);   
4199
4200  sprintf(query_base_dn, "%s%s", ADDRESS_LIST_PREFIX, dn_path);
4201  query_base_dn_v[0] = query_base_dn;
4202
4203  mail_nickname_v[0] = user_name;
4204
4205  memset(mail, '\0', sizeof(mail));
4206  sprintf(mail, "%s@%s", user_name, lowercase(ldap_domain));
4207  memset(alt_recipient, '\0', sizeof(alt_recipient));
4208  sprintf(alt_recipient, "cn=%s@exchange-forwarding.mit.edu,%s,%s", user_name,
4209          contact_ou, dn_path);
4210  sprintf(search_string, "@%s", uppercase(ldap_domain));
4211  memset(filesys_name, '\0', sizeof(filesys_name));
4212  sprintf(filesys_name, "%s.po", user_name);
4213
4214  group_count = 0;
4215  group_base = NULL;
4216
4217  memset(displayName, '\0', sizeof(displayName));
4218
4219  if (strlen(MoiraId) != 0)
4220    {
4221      if(ActiveDirectory)
4222        {
4223          sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
4224        }
4225      else
4226        {
4227          sprintf(filter,
4228                  "(&(objectClass=mitPerson)(mitMoiraId=%s))", MoiraId);
4229        }
4230
4231      attr_array[0] = "cn";
4232      attr_array[1] = NULL;
4233      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
4234                               &group_base, &group_count,
4235                               LDAP_SCOPE_SUBTREE)) != 0)
4236        {
4237          com_err(whoami, 0, "Unable to process user %s : %s",
4238                  user_name, ldap_err2string(rc));
4239          return(rc);
4240        }
4241    }
4242
4243  if (group_count != 1)
4244    {
4245      linklist_free(group_base);
4246      group_base = NULL;
4247      group_count = 0;
4248      sprintf(filter, "(sAMAccountName=%s)", user_name);
4249      attr_array[0] = "cn";
4250      attr_array[1] = NULL;
4251      sprintf(temp, "%s,%s", user_ou, dn_path);
4252      if ((rc = linklist_build(ldap_handle, temp, filter, attr_array,
4253                               &group_base, &group_count,
4254                               LDAP_SCOPE_SUBTREE)) != 0)
4255        {
4256          com_err(whoami, 0, "Unable to process user %s : %s",
4257                  user_name, ldap_err2string(rc));
4258          return(rc);
4259        }
4260    }
4261
4262  if (group_count != 1)
4263    {
4264      com_err(whoami, 0, "Unable to find user %s in directory",
4265              user_name);
4266      linklist_free(group_base);
4267      return(AD_NO_USER_FOUND);
4268    }
4269
4270  strcpy(distinguished_name, group_base->dn);
4271
4272  linklist_free(group_base);
4273  group_count = 0;
4274
4275  if (Exchange)
4276    {
4277      if(contact_create(ldap_handle, dn_path, contact_mail, contact_ou))
4278        {
4279          com_err(whoami, 0, "Unable to create user contact %s", contact_mail);
4280        }
4281
4282      if ((State == US_NO_PASSWD) || (State == US_REGISTERED))
4283        {
4284          group_count = 0;
4285          group_base = NULL;
4286
4287          sprintf(filter,
4288                  "(&(objectClass=user)(homeMDB=*)(sAMAccountName=%s))",
4289                  user_name);
4290
4291          attr_array[0] = "homeMDB";
4292          attr_array[1] = NULL;
4293
4294          if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
4295                                   &group_base, &group_count,
4296                                   LDAP_SCOPE_SUBTREE)) != 0)
4297            {
4298              com_err(whoami, 0, "Unable to process user %s : %s",
4299                      user_name, ldap_err2string(rc));
4300              return(rc);
4301            }
4302
4303          if(group_count == 0)
4304            {
4305              if(find_homeMDB(ldap_handle, dn_path, &homeMDB, &homeServerName))
4306                {
4307                  com_err(whoami, 0,
4308                          "Unable to locate homeMDB and homeServerName");
4309                  return(1);
4310                }
4311
4312              com_err(whoami, 0, "homeMDB:%s", homeMDB);
4313              com_err(whoami, 0, "homeServerName:%s", homeServerName);
4314
4315              homeMDB_v[0] = homeMDB;
4316              homeServerName_v[0] = homeServerName;
4317
4318              n = 0;
4319              hide_address_lists_v[0] = "FALSE";
4320              ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4321                       LDAP_MOD_ADD);
4322              ADD_ATTR("msExchQueryBaseDN", query_base_dn_v, LDAP_MOD_REPLACE);
4323              ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_ADD);
4324              ADD_ATTR("homeMDB", homeMDB_v, LDAP_MOD_ADD);
4325              mdbUseDefaults_v[0] = "TRUE";
4326              ADD_ATTR("mdbUseDefaults", mdbUseDefaults_v, LDAP_MOD_ADD);
4327              ADD_ATTR("msExchHomeServerName", homeServerName_v, LDAP_MOD_ADD);
4328
4329              mods[n] = NULL;
4330              rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4331
4332              if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
4333                rc = LDAP_SUCCESS;
4334             
4335              if(rc)
4336                {
4337                  com_err(whoami, 0,
4338                          "Unable to set the exchange attributes for %s : %s",
4339                          user_name, ldap_err2string(rc));
4340                  return(rc);
4341                }
4342            }
4343
4344          linklist_free(group_base);
4345          group_count = 0;
4346        }
4347    }
4348
4349  if(!ActiveDirectory)
4350    {
4351      if (rc = moira_connect())
4352        {
4353          critical_alert(whoami, "Ldap incremental",
4354                         "Error contacting Moira server : %s",
4355                         error_message(rc));
4356          return;
4357        }
4358 
4359      argv[0] = filesys_name;
4360
4361      if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info,
4362                          save_argv)))
4363        {
4364          n = 0;
4365          ADD_ATTR("mitMoiraIMAPAddress", mit_moira_imap_address_v,
4366                   LDAP_MOD_REPLACE);
4367          mods[n] = NULL;
4368          rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4369         
4370          if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
4371            rc = LDAP_SUCCESS;
4372
4373          if(rc)
4374            com_err(whoami, 0,
4375                    "Unable to set the mitMoiraIMAPAddress for %s : %s",
4376                    user_name, ldap_err2string(rc));
4377
4378          sprintf(temp, "%s@%s", user_name, save_argv[FS_MACHINE]);
4379         
4380          mit_moira_imap_address_v[0]  = temp;
4381               
4382          n = 0;
4383          ADD_ATTR("mitMoiraIMAPAddress", mit_moira_imap_address_v,
4384                   LDAP_MOD_ADD);
4385          mods[n] = NULL;
4386          rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4387         
4388          if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
4389            rc = LDAP_SUCCESS;
4390         
4391          if(rc)
4392            com_err(whoami, 0, "Unable to set the mitMoiraIMAPAddress for "
4393                    "%s : %s", user_name, ldap_err2string(rc));   
4394        } else if(rc==MR_NO_MATCH) {
4395         
4396          n = 0;
4397          ADD_ATTR("mitMoiraIMAPServer", mit_moira_imap_address_v,
4398                   LDAP_MOD_REPLACE);
4399          mods[n] = NULL;
4400          rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4401         
4402          if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
4403            rc = LDAP_SUCCESS;
4404
4405          if(rc)
4406            com_err(whoami, 0,
4407                    "Unable to set the mitMoiraIMAPAddress for %s : %s",
4408                    user_name, ldap_err2string(rc));
4409
4410        }
4411   
4412      argv[0] = user_name;
4413         
4414      if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
4415        {
4416          n = 0;
4417          ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_REPLACE);
4418          mods[n] = NULL;
4419          rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4420         
4421          if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
4422            rc = LDAP_SUCCESS;
4423
4424          if(rc)
4425            com_err(whoami, 0,
4426                    "Unable to set the mailRoutingAddress for %s : %s",
4427                    user_name, ldap_err2string(rc));
4428         
4429          p = strdup(save_argv[3]);
4430         
4431          if((c = strchr(p, ',')) != NULL)
4432            {
4433              q = strtok(p, ",");
4434              StringTrim(q);
4435
4436              if ((c = strchr(q, '@')) == NULL)
4437                sprintf(temp, "%s@mit.edu", q);
4438              else
4439                sprintf(temp, "%s", q);
4440             
4441              if(email_isvalid(temp) && State != US_DELETED)
4442                {
4443                  mail_routing_v[0]  = temp;
4444                 
4445                  n = 0;
4446                  ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
4447                  mods[n] = NULL;
4448                  rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4449
4450                  if (rc == LDAP_ALREADY_EXISTS ||
4451                      rc == LDAP_TYPE_OR_VALUE_EXISTS)
4452                    rc = LDAP_SUCCESS;
4453   
4454                  if(rc)
4455                    com_err(whoami, 0,
4456                            "Unable to set the mailRoutingAddress for %s : %s",
4457                            user_name, ldap_err2string(rc));
4458                }
4459
4460              while((q = strtok(NULL, ",")) != NULL) {
4461                StringTrim(q);
4462               
4463                if((c = strchr(q, '@')) == NULL)
4464                  sprintf(temp, "%s@mit.edu", q);
4465                else
4466                  sprintf(temp, "%s", q);
4467
4468                if(email_isvalid(temp) && State != US_DELETED)
4469                  {
4470                    mail_routing_v[0]  = temp;
4471               
4472                    n = 0;
4473                    ADD_ATTR("mailRoutingAddress", mail_routing_v,
4474                             LDAP_MOD_ADD);
4475                    mods[n] = NULL;
4476                    rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4477                   
4478                    if (rc == LDAP_ALREADY_EXISTS ||
4479                        rc == LDAP_TYPE_OR_VALUE_EXISTS)
4480                      rc = LDAP_SUCCESS;
4481                   
4482                    if(rc)
4483                      com_err(whoami, 0,
4484                              "Unable to set the mailRoutingAddress for "
4485                              "%s : %s",
4486                              user_name, ldap_err2string(rc));
4487                  }
4488              }
4489            } else {
4490              StringTrim(p);
4491
4492            if((c = strchr(p, '@')) == NULL)
4493              sprintf(temp, "%s@mit.edu", p);
4494            else
4495              sprintf(temp, "%s", p);
4496           
4497            if(email_isvalid(temp) && State != US_DELETED)
4498              {
4499                mail_routing_v[0]  = temp;
4500               
4501                n = 0;
4502                ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
4503                mods[n] = NULL;
4504                rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4505               
4506                if (rc == LDAP_ALREADY_EXISTS ||
4507                    rc == LDAP_TYPE_OR_VALUE_EXISTS)
4508                  rc = LDAP_SUCCESS;
4509               
4510                if(rc)
4511                  com_err(whoami, 0,
4512                          "Unable to set the mailRoutingAddress for %s : %s",
4513                          user_name, ldap_err2string(rc));
4514              }
4515            }
4516        } else if(rc==MR_NO_MATCH) {
4517         
4518          n = 0;
4519          ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_REPLACE);
4520          mods[n] = NULL;
4521          rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4522         
4523          if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
4524            rc = LDAP_SUCCESS;
4525
4526          if(rc)
4527            com_err(whoami, 0,
4528                    "Unable to set the mailRoutingAddress for %s : %s",
4529                    user_name, ldap_err2string(rc));
4530        }
4531      moira_disconnect();
4532    }
4533
4534  if ((strlen(MitId) != 0) && (MitId[0] == '9'))
4535    rc = attribute_update(ldap_handle, distinguished_name, MitId,
4536                          "employeeID", user_name);
4537  else
4538    rc = attribute_update(ldap_handle, distinguished_name, "none",
4539                          "employeeID", user_name);
4540
4541  if(strlen(first)) {
4542    strcat(displayName, first);
4543  }
4544
4545  if(strlen(middle)) {
4546    if(strlen(first))
4547      strcat(displayName, " ");
4548
4549    strcat(displayName, middle);
4550  }
4551
4552  if(strlen(last)) {
4553    if(strlen(middle) || strlen(first))
4554      strcat(displayName, " ");
4555
4556    strcat(displayName, last);
4557  }
4558
4559  if(strlen(displayName))
4560    rc = attribute_update(ldap_handle, distinguished_name, displayName,
4561                          "displayName", user_name);
4562  else
4563    rc = attribute_update(ldap_handle, distinguished_name, user_name,
4564                          "displayName", user_name);
4565
4566  if(!ActiveDirectory)
4567    {
4568      if(strlen(displayName))
4569        rc = attribute_update(ldap_handle, distinguished_name, displayName,
4570                              "cn", user_name);
4571      else
4572        rc = attribute_update(ldap_handle, distinguished_name, user_name,
4573                              "cn", user_name);
4574    }
4575
4576  if(!ActiveDirectory)
4577    {
4578      rc = attribute_update(ldap_handle, distinguished_name, displayName,
4579                            "eduPersonNickname", user_name);
4580    }
4581
4582  if(strlen(first))
4583    rc = attribute_update(ldap_handle, distinguished_name, first,
4584                          "givenName", user_name);
4585  else
4586    rc = attribute_update(ldap_handle, distinguished_name, "",
4587                          "givenName", user_name);
4588
4589  if(strlen(middle) == 1)
4590    rc = attribute_update(ldap_handle, distinguished_name, middle,
4591                          "initials", user_name);
4592  else
4593    rc = attribute_update(ldap_handle, distinguished_name, "",
4594                          "initials", user_name);
4595 
4596  if(strlen(last))
4597    rc = attribute_update(ldap_handle, distinguished_name, last,
4598                          "sn", user_name);
4599  else
4600    rc = attribute_update(ldap_handle, distinguished_name, "",
4601                          "sn", user_name);
4602
4603  if(ActiveDirectory)
4604    {
4605      rc = attribute_update(ldap_handle, distinguished_name, Uid, "uid",
4606                            user_name);
4607    }
4608  else
4609    {
4610      rc = attribute_update(ldap_handle, distinguished_name, user_name, "uid",
4611                            user_name);
4612    }
4613   
4614  rc = attribute_update(ldap_handle, distinguished_name, MoiraId,
4615                        "mitMoiraId", user_name);
4616
4617  n = 0;
4618  uid_v[0] = Uid;
4619
4620  if(ActiveDirectory)
4621    {
4622      if (!UseSFU30)
4623        {
4624          ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
4625        }
4626      else
4627        {
4628          ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_REPLACE);
4629        }
4630    }
4631  else
4632    {
4633      sprintf(principal, "%s@%s", user_name, PRIMARY_REALM);
4634      sprintf(status, "%d", State);
4635      principal_v[0] = principal;
4636      loginshell_v[0] = shell;
4637      mitMoiraClass_v[0] = class;
4638      mitMoiraStatus_v[0] = status;
4639      gid_v[0] = "101";
4640      ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
4641      ADD_ATTR("gidNumber", gid_v, LDAP_MOD_REPLACE);
4642      ADD_ATTR("loginShell", loginshell_v, LDAP_MOD_REPLACE);
4643      ADD_ATTR("eduPersonPrincipalName", mail_v, LDAP_MOD_REPLACE);
4644      ADD_ATTR("mitMoiraClass", mitMoiraClass_v, LDAP_MOD_REPLACE);
4645      ADD_ATTR("mitMoiraStatus", mitMoiraStatus_v, LDAP_MOD_REPLACE);
4646    }
4647
4648  if ((State != US_NO_PASSWD) && (State != US_REGISTERED))
4649    {
4650      userAccountControl |= UF_ACCOUNTDISABLE;
4651
4652      if (Exchange)
4653        {
4654          hide_address_lists_v[0] = "TRUE";
4655          ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4656                   LDAP_MOD_REPLACE);
4657        }
4658    }
4659  else
4660    {
4661      if (Exchange)
4662        {
4663          hide_address_lists_v[0] = NULL;
4664          ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4665                   LDAP_MOD_REPLACE);
4666        }
4667    }
4668
4669  sprintf(userAccountControlStr, "%ld", userAccountControl);
4670  userAccountControl_v[0] = userAccountControlStr;
4671  ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_REPLACE);
4672
4673  if (Exchange)
4674    {
4675      if (rc = moira_connect())
4676        {
4677          critical_alert(whoami, "Ldap incremental",
4678                         "Error contacting Moira server : %s",
4679                         error_message(rc));
4680          return;
4681        }
4682 
4683      argv[0] = user_name;
4684
4685      if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
4686        {
4687          if(!strcmp(save_argv[1], "EXCHANGE") ||
4688             (strstr(save_argv[3], search_string) != NULL))
4689            {
4690              alt_recipient_v[0] = NULL;
4691              ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_REPLACE);
4692
4693              argv[0] = exchange_acl;
4694              argv[1] = "USER";
4695              argv[2] = user_name;
4696             
4697              rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
4698             
4699              if ((rc) && (rc != MR_EXISTS))
4700                {
4701                  com_err(whoami, 0, "Unable to add user %s to %s: %s",
4702                          user_name, exchange_acl, error_message(rc));
4703                }
4704
4705              if(!strcmp(save_argv[1], "SPLIT") ||
4706                 !strcmp(save_argv[1], "SMTP")) {
4707
4708                deliver_and_redirect_v[0] = "TRUE";
4709                alt_recipient_v[0] = alt_recipient;
4710                ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_REPLACE);
4711                ADD_ATTR("deliverAndRedirect", deliver_and_redirect_v,
4712                         LDAP_MOD_REPLACE);
4713              }
4714            }
4715          else
4716            {
4717              deliver_and_redirect_v[0] = "FALSE";
4718              alt_recipient_v[0] = alt_recipient;
4719              ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_REPLACE);
4720              ADD_ATTR("deliverAndRedirect", deliver_and_redirect_v,
4721                       LDAP_MOD_REPLACE);
4722             
4723              argv[0] = exchange_acl;
4724              argv[1] = "USER";
4725              argv[2] = user_name;
4726             
4727              rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
4728             
4729              if ((rc) && (rc != MR_NO_MATCH))
4730                { 
4731                  com_err(whoami, 0,
4732                          "Unable to remove user %s from %s: %s, %d",
4733                          user_name, exchange_acl, error_message(rc), rc);
4734                } 
4735            }
4736        }
4737      else
4738        {
4739          deliver_and_redirect_v[0] = "FALSE";
4740          alt_recipient_v[0] = alt_recipient;
4741          ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_REPLACE);
4742          ADD_ATTR("deliverAndRedirect", deliver_and_redirect_v,
4743                   LDAP_MOD_REPLACE);     
4744
4745          argv[0] = exchange_acl;
4746          argv[1] = "USER";
4747          argv[2] = user_name;
4748         
4749          rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
4750         
4751          if ((rc) && (rc != MR_NO_MATCH))
4752            { 
4753              com_err(whoami, 0,
4754                      "Unable to remove user %s from %s: %s, %d",
4755                      user_name, exchange_acl, error_message(rc), rc);
4756            } 
4757        }
4758     
4759      moira_disconnect();
4760    }
4761  else
4762    {
4763      mail_v[0] = contact_mail;
4764      ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
4765
4766      if(!ActiveDirectory)
4767        {
4768          ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_REPLACE);
4769        }
4770    }
4771
4772  n = SetHomeDirectory(ldap_handle, user_name, distinguished_name, WinHomeDir,
4773                       WinProfileDir, homedir_v, winProfile_v,
4774                       drives_v, apple_homedir_v, mods, LDAP_MOD_REPLACE, n);
4775
4776  if(ActiveDirectory)
4777    {
4778      sprintf(filter_exp, "(sAMAccountName=%s)", "UserTemplate.u");
4779      sprintf(search_path, "%s,%s", security_template_ou, dn_path);
4780      attr_array[0] = "sAMAccountName";
4781      attr_array[1] = NULL;
4782      group_count = 0;
4783      group_base = NULL;
4784   
4785      if ((rc = linklist_build(ldap_handle, search_path, filter_exp,
4786                               attr_array,
4787                               &group_base, &group_count,
4788                               LDAP_SCOPE_SUBTREE) != 0))
4789        return(1);
4790     
4791      if (group_count != 1)
4792        {
4793          com_err(whoami, 0, "Unable to process user security template: %s - "
4794                  "security not set", "UserTemplate.u");
4795          return(1);
4796        }
4797
4798      strcpy(TemplateDn, group_base->dn);
4799      strcpy(TemplateSamName, group_base->value);
4800      linklist_free(group_base);
4801      group_base = NULL;
4802      group_count = 0;
4803     
4804      rc = ldap_search_ext_s(ldap_handle, search_path, LDAP_SCOPE_SUBTREE,
4805                             filter_exp, NULL, 0, apsServerControls, NULL,
4806                             NULL, 0, &psMsg);
4807
4808      if ((psMsg = ldap_first_entry(ldap_handle, psMsg)) == NULL)
4809        {
4810          com_err(whoami, 0, "Unable to find user security template: %s - "
4811                  "security not set", "UserTemplate.u");
4812          return(1);
4813        }
4814     
4815      ppsValues = ldap_get_values_len(ldap_handle, psMsg,
4816                                      "ntSecurityDescriptor");
4817
4818      if (ppsValues == NULL)
4819        {
4820          com_err(whoami, 0, "Unable to find user security template: %s - "
4821                  "security not set", "UserTemplate.u");
4822          return(1);
4823        }
4824     
4825      ADD_ATTR("ntSecurityDescriptor", (char **)ppsValues,
4826               LDAP_MOD_REPLACE | LDAP_MOD_BVALUES);
4827    }
4828
4829  mods[n] = NULL;
4830
4831  if ((rc = ldap_modify_s(ldap_handle, distinguished_name,
4832                          mods)) != LDAP_SUCCESS)
4833    {
4834      OldUseSFU30 = UseSFU30;
4835      SwitchSFU(mods, &UseSFU30, n);
4836      if (OldUseSFU30 != UseSFU30)
4837        rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4838      if (rc)
4839        {
4840          com_err(whoami, 0, "Unable to modify user data for %s : %s",
4841                  user_name, ldap_err2string(rc));
4842        }
4843    }
4844 
4845  for (i = 0; i < n; i++)
4846    free(mods[i]);
4847
4848  return(rc);
4849}
4850
4851int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name,
4852                char *user_name)
4853{
4854  LDAPMod *mods[20];
4855  char new_dn[256];
4856  char old_dn[256];
4857  char upn[256];
4858  char mail[256];
4859  char contact_mail[256];
4860  char proxy_address[256];
4861  char proxy_address_mit[256];
4862  char proxy_address_x500[256];
4863  char query_base_dn[256];
4864  char temp[256];
4865  char *userPrincipalName_v[] = {NULL, NULL};
4866  char *altSecurityIdentities_v[] = {NULL, NULL};
4867  char *name_v[] = {NULL, NULL};
4868  char *samAccountName_v[] = {NULL, NULL};
4869  char *mail_v[] = {NULL, NULL};
4870  char *mail_nickname_v[] = {NULL, NULL};
4871  char *proxy_address_v[] = {NULL, NULL, NULL, NULL};
4872  char *query_base_dn_v[] = {NULL, NULL};
4873  char *principal_v[] = {NULL, NULL};
4874  char principal[256];
4875  int  n;
4876  int  rc;
4877  int  i;
4878
4879  if (!check_string(before_user_name))
4880    {
4881      com_err(whoami, 0,
4882              "Unable to process invalid LDAP user name %s", before_user_name);
4883      return(AD_INVALID_NAME);
4884    }
4885
4886  if (!check_string(user_name))
4887    {
4888      com_err(whoami, 0,
4889              "Unable to process invalid LDAP user name %s", user_name);
4890      return(AD_INVALID_NAME);
4891    }
4892
4893  strcpy(user_name, user_name);
4894 
4895  if(ActiveDirectory)
4896    sprintf(old_dn, "cn=%s,%s,%s", before_user_name, user_ou, dn_path);
4897  else
4898    sprintf(old_dn, "uid=%s,%s,%s", before_user_name, user_ou, dn_path);
4899
4900  if(ActiveDirectory)
4901    sprintf(new_dn, "cn=%s", user_name);
4902  else
4903    sprintf(new_dn, "uid=%s", user_name);
4904
4905  sprintf(mail, "%s@%s", user_name, lowercase(ldap_domain));
4906  if(Exchange)
4907    sprintf(contact_mail, "%s@exchange-forwarding.mit.edu", user_name);
4908  else
4909    sprintf(contact_mail, "%s@mit.edu", user_name);
4910  sprintf(proxy_address, "smtp:%s@%s", user_name, lowercase(ldap_domain));
4911  sprintf(proxy_address_mit, "SMTP:%s@mit.edu", user_name);
4912  sprintf(proxy_address_x500, "%s/cn=%s?mit.edu", X500_PREFIX, user_name);
4913 
4914  sprintf(principal, "%s@%s", user_name, PRIMARY_REALM);
4915
4916  if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, NULL, TRUE,
4917                           NULL, NULL)) != LDAP_SUCCESS)
4918    {
4919      com_err(whoami, 0, "Unable to rename user from %s to %s : %s",
4920              before_user_name, user_name, ldap_err2string(rc));
4921      return(rc);
4922    }
4923
4924  if (Exchange)
4925    {
4926      sprintf(temp, "cn=%s@exchange-forwarding.mit.edu,%s,%s", before_user_name,
4927              contact_ou, dn_path);
4928
4929      if(rc = ldap_delete_s(ldap_handle, temp))
4930        {
4931          com_err(whoami, 0, "Unable to delete user contact for %s",
4932                  user_name);
4933        }
4934     
4935      if(contact_create(ldap_handle, dn_path, contact_mail, contact_ou))
4936        {
4937          com_err(whoami, 0, "Unable to create user contact %s", contact_mail);
4938        }
4939    }
4940
4941  name_v[0] = user_name;
4942  sprintf(upn, "%s@%s", user_name, ldap_domain);
4943  userPrincipalName_v[0] = upn;
4944  principal_v[0] = principal;
4945  sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
4946  sprintf(query_base_dn, "%s%s", ADDRESS_LIST_PREFIX, dn_path);
4947  altSecurityIdentities_v[0] = temp;
4948  samAccountName_v[0] = user_name;
4949  mail_v[0] = mail;
4950  mail_nickname_v[0] = user_name;
4951  proxy_address_v[0] = proxy_address_mit;
4952  proxy_address_v[1] = proxy_address;
4953  query_base_dn_v[0] = query_base_dn;
4954
4955  n = 0;
4956  ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_REPLACE);
4957  ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_REPLACE);
4958  ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
4959  ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_REPLACE);
4960
4961  if(!ActiveDirectory)
4962    {
4963      ADD_ATTR("uid", samAccountName_v, LDAP_MOD_REPLACE);
4964      ADD_ATTR("eduPersonPrincipalName", mail_v, LDAP_MOD_REPLACE);
4965      ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
4966      ADD_ATTR("eduPersonNickname", name_v, LDAP_MOD_REPLACE);
4967    }
4968
4969  if (Exchange)
4970    {
4971      ADD_ATTR("msExchQueryBaseDN", query_base_dn_v, LDAP_MOD_REPLACE);
4972      ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
4973      ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
4974      ADD_ATTR("proxyAddresses", proxy_address_v, LDAP_MOD_REPLACE);
4975    }
4976  else
4977    {
4978      mail_v[0] = contact_mail;
4979      ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
4980
4981      if(!ActiveDirectory)
4982        {
4983          ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_REPLACE);
4984        }
4985    }
4986
4987  mods[n] = NULL;
4988 
4989  if(ActiveDirectory)
4990    sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, dn_path);
4991  else
4992    sprintf(new_dn, "uid=%s,%s,%s", user_name, user_ou, dn_path);
4993
4994  if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
4995    {
4996      com_err(whoami, 0,
4997              "Unable to modify user data for %s after renaming : %s",
4998              user_name, ldap_err2string(rc));
4999    }
5000 
5001  for (i = 0; i < n; i++)
5002    free(mods[i]);
5003
5004  return(rc);
5005}
5006
5007int user_create(int ac, char **av, void *ptr)
5008{
5009  LDAPMod *mods[40];
5010  char new_dn[256];
5011  char user_name[256];
5012  char sam_name[256];
5013  char upn[256];
5014  char mail[256];
5015  char contact_mail[256];
5016  char proxy_address[256];
5017  char mail_nickname[256];
5018  char query_base_dn[256];
5019  char displayName[256];
5020  char address_book[1024];
5021  char alt_recipient[256];
5022  char filesys_name[256];
5023  char *cn_v[] = {NULL, NULL};
5024  char *objectClass_v[] = {"top", "person", "organizationalPerson",
5025                           "user", NULL};
5026  char *objectClass_ldap_v[] = {"top",
5027                                "eduPerson", "posixAccount",
5028                                "apple-user", "shadowAccount",
5029                                "microsoftComTop", "securityPrincipal",
5030                                "inetOrgPerson", "user",
5031                                "organizationalPerson", "person",
5032                                "mailRecipient", NULL};
5033
5034  char *samAccountName_v[] = {NULL, NULL};
5035  char *altSecurityIdentities_v[] = {NULL, NULL};
5036  char *mitMoiraId_v[] = {NULL, NULL};
5037  char *mitMoiraClass_v[] = {NULL, NULL};
5038  char *mitMoiraStatus_v[] = {NULL, NULL};
5039  char *name_v[] = {NULL, NULL};
5040  char *desc_v[] = {NULL, NULL};
5041  char *userPrincipalName_v[] = {NULL, NULL};
5042  char *userAccountControl_v[] = {NULL, NULL};
5043  char *uid_v[] = {NULL, NULL};
5044  char *gid_v[] = {NULL, NULL};
5045  char *mitid_v[] = {NULL, NULL};
5046  char *homedir_v[] = {NULL, NULL};
5047  char *apple_homedir_v[] = {NULL, NULL};
5048  char *winProfile_v[] = {NULL, NULL};
5049  char *drives_v[] = {NULL, NULL};
5050  char *mail_v[] = {NULL, NULL};
5051  char *givenName_v[] = {NULL, NULL};
5052  char *sn_v[] = {NULL, NULL};
5053  char *initials_v[] = {NULL, NULL};
5054  char *displayName_v[] = {NULL, NULL};
5055  char *proxy_address_v[] = {NULL, NULL};
5056  char *mail_nickname_v[] = {NULL, NULL};
5057  char *query_base_dn_v[] = {NULL, NULL};
5058  char *address_book_v[] = {NULL, NULL, NULL, NULL, NULL};
5059  char *homeMDB_v[] = {NULL, NULL};
5060  char *homeServerName_v[] = {NULL, NULL};
5061  char *mdbUseDefaults_v[] = {NULL, NULL};
5062  char *mailbox_guid_v[] = {NULL, NULL};
5063  char *user_culture_v[] = {NULL, NULL};
5064  char *user_account_control_v[] = {NULL, NULL};
5065  char *msexch_version_v[] = {NULL, NULL};
5066  char *alt_recipient_v[] = {NULL, NULL};
5067  char *hide_address_lists_v[] = {NULL, NULL};
5068  char *principal_v[] = {NULL, NULL};
5069  char *loginshell_v[] = {NULL, NULL};
5070  char userAccountControlStr[80];
5071  char temp[1024];
5072  char principal[256];
5073  char filter_exp[1024];
5074  char search_path[512];
5075  char *attr_array[3];
5076  u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD |
5077    UF_PASSWD_CANT_CHANGE;
5078  int  n;
5079  int  rc;
5080  int  i;
5081  int  OldUseSFU30;
5082  char **call_args;
5083  char WinHomeDir[1024];
5084  char WinProfileDir[1024];
5085  char *homeMDB;
5086  char *homeServerName;
5087  ULONG dwInfo;
5088  char acBERBuf[N_SD_BER_BYTES];
5089  LK_ENTRY  *group_base;
5090  int    group_count;
5091  char TemplateDn[512];
5092  char TemplateSamName[128];
5093  LDAP_BERVAL **ppsValues;
5094  LDAPControl sControl = {"1.2.840.113556.1.4.801",
5095                          { N_SD_BER_BYTES, acBERBuf },
5096                          TRUE};
5097  LDAPControl *apsServerControls[] = {&sControl, NULL};
5098  LDAPMessage *psMsg;
5099  char *argv[3];
5100  char *save_argv[7];
5101  char search_string[256];
5102  char *o_v[] = {NULL, NULL};
5103  char *p, *q;
5104  char *mail_routing_v[] = {NULL, NULL};
5105  char *mail_alternate_v[] = {NULL, NULL};
5106  char *mit_moira_imap_address_v[] = {NULL, NULL};
5107  char *deliver_and_redirect_v[] = {NULL, NULL};
5108  char *c;
5109
5110  call_args = ptr;
5111
5112  dwInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
5113    DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
5114  BEREncodeSecurityBits(dwInfo, acBERBuf);
5115
5116  if (!check_string(av[U_NAME]))
5117    {
5118      callback_rc = AD_INVALID_NAME;
5119      com_err(whoami, 0, "Unable to process invalid LDAP user name %s",
5120              av[U_NAME]);
5121      return(AD_INVALID_NAME);
5122    }
5123
5124  memset(WinHomeDir, '\0', sizeof(WinHomeDir));
5125  memset(WinProfileDir, '\0', sizeof(WinProfileDir));
5126  memset(displayName, '\0', sizeof(displayName));
5127  memset(query_base_dn, '\0', sizeof(query_base_dn));
5128  memset(filesys_name, '\0', sizeof(filesys_name));
5129  strcpy(WinHomeDir, av[U_WINHOMEDIR]);
5130  strcpy(WinProfileDir, av[U_WINPROFILEDIR]);
5131  strcpy(user_name, av[U_NAME]);
5132  sprintf(upn, "%s@%s", user_name, ldap_domain);
5133  sprintf(sam_name, "%s", av[U_NAME]);
5134  sprintf(filesys_name, "%s.po", user_name);
5135
5136  if(strlen(av[U_FIRST])) {
5137    strcat(displayName, av[U_FIRST]);
5138  }
5139
5140  if(strlen(av[U_MIDDLE])) {
5141    if(strlen(av[U_FIRST]))
5142       strcat(displayName, " ");
5143 
5144    strcat(displayName, av[U_MIDDLE]);
5145  }
5146
5147  if(strlen(av[U_LAST])) {
5148    if(strlen(av[U_FIRST]) || strlen(av[U_MIDDLE]))
5149      strcat(displayName, " ");
5150
5151    strcat(displayName, av[U_LAST]);
5152  }
5153
5154  samAccountName_v[0] = sam_name;
5155
5156  if ((atoi(av[U_STATE]) != US_NO_PASSWD) &&
5157      (atoi(av[U_STATE]) != US_REGISTERED))
5158    {
5159      userAccountControl |= UF_ACCOUNTDISABLE;
5160    }
5161
5162  sprintf(userAccountControlStr, "%ld", userAccountControl);
5163  userAccountControl_v[0] = userAccountControlStr;
5164  userPrincipalName_v[0] = upn;
5165 
5166  if(ActiveDirectory)
5167    cn_v[0] = user_name;
5168  else
5169    cn_v[0] = displayName;
5170   
5171  name_v[0] = user_name;
5172  desc_v[0] = "Auto account created by Moira";
5173  mail_v[0] = mail;
5174  givenName_v[0] = av[U_FIRST];
5175
5176  if(ActiveDirectory)
5177    sn_v[0] = av[U_LAST];
5178  else
5179    if(strlen(av[U_LAST]))
5180      sn_v[0] = av[U_LAST];
5181    else
5182      sn_v[0] = av[U_NAME];
5183
5184  displayName_v[0] = displayName;
5185  mail_nickname_v[0] = user_name;
5186  o_v[0] = "Massachusetts Institute of Technology";
5187
5188  sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
5189  sprintf(principal, "%s@%s", user_name, PRIMARY_REALM);
5190  altSecurityIdentities_v[0] = temp;   
5191  principal_v[0] = principal;
5192
5193  if(ActiveDirectory)
5194    sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, call_args[1]);
5195  else
5196    sprintf(new_dn, "uid=%s,%s,%s", user_name, user_ou, call_args[1]);
5197
5198  sprintf(mail,"%s@%s", user_name, lowercase(ldap_domain));
5199  if(Exchange)
5200    sprintf(contact_mail, "%s@exchange-forwarding.mit.edu", user_name);
5201  else
5202    sprintf(contact_mail, "%s@mit.edu", user_name);   
5203  sprintf(query_base_dn, "%s%s", ADDRESS_LIST_PREFIX, call_args[1]);
5204  query_base_dn_v[0] = query_base_dn;
5205  sprintf(alt_recipient, "cn=%s@exchange-forwarding.mit.edu,%s,%s", user_name,
5206          contact_ou, call_args[1]);
5207  sprintf(search_string, "@%s", uppercase(ldap_domain));
5208
5209  if (Exchange)
5210    {
5211      if(contact_create((LDAP *)call_args[0], call_args[1], contact_mail,
5212                        contact_ou))
5213        {
5214          com_err(whoami, 0, "Unable to create user contact %s",
5215                  contact_mail);
5216        }
5217     
5218      if(find_homeMDB((LDAP *)call_args[0], call_args[1], &homeMDB,
5219                      &homeServerName))
5220        {
5221          com_err(whoami, 0, "Unable to locate homeMB and homeServerName");
5222          return(1);
5223        }
5224     
5225      com_err(whoami, 0, "homeMDB:%s", homeMDB);
5226      com_err(whoami, 0, "homeServerName:%s", homeServerName);
5227 
5228      homeMDB_v[0] = homeMDB;
5229      homeServerName_v[0] = homeServerName;
5230    }
5231
5232  n = 0;
5233
5234  ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
5235 
5236  if(ActiveDirectory)
5237    {
5238      ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
5239    }
5240  else
5241    {
5242      ADD_ATTR("objectClass", objectClass_ldap_v, LDAP_MOD_ADD);
5243    }
5244
5245  ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
5246  ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_ADD);
5247  ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_ADD);
5248  ADD_ATTR("name", name_v, LDAP_MOD_ADD);
5249  ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
5250
5251  if (Exchange)
5252    {
5253      if ((atoi(av[U_STATE]) != US_NO_PASSWD) &&
5254          (atoi(av[U_STATE]) != US_REGISTERED))
5255        {
5256          hide_address_lists_v[0] = "TRUE";
5257          ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
5258                   LDAP_MOD_ADD);
5259        }
5260      else
5261        {
5262          hide_address_lists_v[0] = "FALSE";
5263          ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
5264                   LDAP_MOD_ADD);
5265        }
5266
5267      ADD_ATTR("msExchQueryBaseDN", query_base_dn_v, LDAP_MOD_ADD);
5268      ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_ADD);
5269      ADD_ATTR("homeMDB", homeMDB_v, LDAP_MOD_ADD);
5270      mdbUseDefaults_v[0] = "TRUE";
5271      ADD_ATTR("mdbUseDefaults", mdbUseDefaults_v, LDAP_MOD_ADD);
5272      ADD_ATTR("msExchHomeServerName", homeServerName_v, LDAP_MOD_ADD);
5273     
5274      argv[0] = user_name;
5275   
5276      if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
5277        {
5278          if(!strcmp(save_argv[1], "EXCHANGE") ||
5279             (strstr(save_argv[3], search_string) != NULL))
5280            {
5281              argv[0] = exchange_acl;
5282              argv[1] = "USER";
5283              argv[2] = user_name;
5284             
5285              rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
5286             
5287              if ((rc) && (rc != MR_EXISTS))
5288                {
5289                  com_err(whoami, 0, "Unable to add user %s to %s: %s",
5290                          user_name, exchange_acl, error_message(rc));
5291                }
5292
5293              if(!strcmp(save_argv[1], "SPLIT") ||
5294                 !strcmp(save_argv[1], "SMTP")) {
5295               
5296                deliver_and_redirect_v[0] = "TRUE";
5297                alt_recipient_v[0] = alt_recipient;
5298
5299                ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_ADD);
5300                ADD_ATTR("deliverAndRedirect", deliver_and_redirect_v,
5301                         LDAP_MOD_ADD);
5302              }
5303            }
5304          else
5305            {
5306              alt_recipient_v[0] = alt_recipient;
5307              ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_ADD);
5308            }
5309        }
5310      else
5311        {
5312          alt_recipient_v[0] = alt_recipient;
5313          ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_ADD);
5314         
5315          com_err(whoami, 0, "Unable to fetch pobox for %s", user_name);
5316        }
5317    }
5318  else
5319    {
5320      mail_v[0] = contact_mail;
5321      ADD_ATTR("mail", mail_v, LDAP_MOD_ADD);
5322
5323      if(!ActiveDirectory)
5324        {
5325          ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_ADD);
5326        }
5327    }
5328
5329  if(strlen(av[U_FIRST])) {
5330    ADD_ATTR("givenName", givenName_v, LDAP_MOD_ADD);
5331  }
5332
5333  if(strlen(av[U_LAST]) || strlen(av[U_NAME])) {
5334    ADD_ATTR("sn", sn_v, LDAP_MOD_ADD);
5335  }
5336
5337  if(strlen(av[U_FIRST]) || strlen(av[U_MIDDLE]) || strlen(av[U_LAST])) {
5338    ADD_ATTR("displayName", displayName_v, LDAP_MOD_ADD);
5339
5340    if(!ActiveDirectory)
5341      {
5342        ADD_ATTR("eduPersonNickname", displayName_v, LDAP_MOD_ADD);     
5343      }
5344  } else {
5345    ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
5346
5347    if(!ActiveDirectory)
5348      {
5349        ADD_ATTR("eduPersonNickname", name_v, LDAP_MOD_ADD);           
5350      }
5351  }
5352
5353  if (strlen(av[U_MIDDLE]) == 1) {
5354    initials_v[0] = av[U_MIDDLE];
5355    ADD_ATTR("initials", initials_v, LDAP_MOD_ADD);
5356  }
5357
5358  if (strlen(call_args[2]) != 0)   
5359    {
5360      mitMoiraId_v[0] = call_args[2];
5361      ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
5362    }
5363
5364  ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_ADD);
5365
5366  if(!ActiveDirectory)
5367    {
5368      loginshell_v[0] = av[U_SHELL];
5369      mitMoiraClass_v[0] = av[U_CLASS];
5370      mitMoiraStatus_v[0] = av[U_STATE];
5371      ADD_ATTR("loginShell", loginshell_v, LDAP_MOD_ADD);
5372      ADD_ATTR("uid", samAccountName_v, LDAP_MOD_ADD);
5373      ADD_ATTR("eduPersonPrincipalName", mail_v, LDAP_MOD_ADD);
5374      ADD_ATTR("o", o_v, LDAP_MOD_ADD);
5375      ADD_ATTR("mitMoiraClass", mitMoiraClass_v, LDAP_MOD_ADD);
5376      ADD_ATTR("mitMoiraStatus", mitMoiraStatus_v, LDAP_MOD_ADD);
5377    }
5378
5379  if (strlen(av[U_UID]) != 0)
5380    {
5381      uid_v[0] = av[U_UID];
5382
5383      if(ActiveDirectory)
5384        {
5385          ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
5386        }
5387      else
5388        {
5389          gid_v[0] = "101";
5390          ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
5391          ADD_ATTR("gidNumber", gid_v, LDAP_MOD_ADD);
5392        }
5393
5394      if(ActiveDirectory)
5395        {
5396          if (!UseSFU30)
5397            {
5398              ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
5399            }
5400          else
5401            {
5402              ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_ADD);
5403            }
5404        }
5405    }
5406
5407  if ((strlen(av[U_MITID]) != 0) && (av[U_MITID][0] == '9'))
5408      mitid_v[0] = av[U_MITID];
5409  else
5410      mitid_v[0] = "none";
5411
5412  ADD_ATTR("employeeID", mitid_v, LDAP_MOD_ADD);
5413
5414  n = SetHomeDirectory((LDAP *)call_args[0], user_name, new_dn,
5415                       WinHomeDir, WinProfileDir, homedir_v, winProfile_v,
5416                       drives_v, apple_homedir_v, mods, LDAP_MOD_ADD, n);
5417 
5418  if(ActiveDirectory)
5419    {
5420      sprintf(filter_exp, "(sAMAccountName=%s)", "UserTemplate.u");
5421      sprintf(search_path, "%s,%s", security_template_ou, call_args[1]);
5422      attr_array[0] = "sAMAccountName";
5423      attr_array[1] = NULL;
5424      group_count = 0;
5425      group_base = NULL;
5426     
5427      if ((rc = linklist_build((LDAP *)call_args[0], search_path, filter_exp,
5428                               attr_array, &group_base, &group_count,
5429                               LDAP_SCOPE_SUBTREE) != 0))
5430        return(1);
5431     
5432      if (group_count != 1)
5433        {
5434          com_err(whoami, 0, "Unable to process user security template: %s - "
5435                  "security not set", "UserTemplate.u");
5436          return(1);
5437        }
5438     
5439      strcpy(TemplateDn, group_base->dn);
5440      strcpy(TemplateSamName, group_base->value);
5441      linklist_free(group_base);
5442      group_base = NULL;
5443      group_count = 0;
5444     
5445      rc = ldap_search_ext_s((LDAP *)call_args[0], search_path,
5446                             LDAP_SCOPE_SUBTREE, filter_exp, NULL, 0,
5447                             apsServerControls, NULL,
5448                             NULL, 0, &psMsg);
5449     
5450      if ((psMsg = ldap_first_entry((LDAP *)call_args[0], psMsg)) == NULL)
5451        {
5452          com_err(whoami, 0, "Unable to find user security template: %s - "
5453                  "security not set", "UserTemplate.u");
5454          return(1);
5455        }
5456     
5457      ppsValues = ldap_get_values_len((LDAP *)call_args[0], psMsg,
5458                                      "ntSecurityDescriptor");
5459      if (ppsValues == NULL)
5460        {
5461          com_err(whoami, 0, "Unable to find user security template: %s - "
5462                  "security not set", "UserTemplate.u");
5463          return(1);
5464        }
5465     
5466      ADD_ATTR("ntSecurityDescriptor", (char **)ppsValues,
5467               LDAP_MOD_REPLACE | LDAP_MOD_BVALUES);
5468    }
5469
5470  mods[n] = NULL;
5471
5472  rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
5473
5474  if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
5475    {
5476      OldUseSFU30 = UseSFU30;
5477      SwitchSFU(mods, &UseSFU30, n);
5478      if (OldUseSFU30 != UseSFU30)
5479        rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
5480    }
5481
5482  for (i = 0; i < n; i++)
5483    free(mods[i]);
5484
5485  if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
5486    {
5487      com_err(whoami, 0, "Unable to create user %s : %s",
5488              user_name, ldap_err2string(rc));
5489      callback_rc = rc;
5490      return(rc);
5491    }
5492
5493  if ((rc == LDAP_SUCCESS) && (SetPassword))
5494    {
5495      if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
5496        {
5497          ad_kdc_disconnect();
5498          if (!ad_server_connect(default_server, ldap_domain))
5499            {
5500              com_err(whoami, 0, "Unable to set password for user %s : %s",
5501                      user_name,
5502                      "cannot get changepw ticket from windows domain");
5503            }
5504          else
5505            {
5506              if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
5507                {
5508                  com_err(whoami, 0, "Unable to set password for user %s "
5509                          ": %ld", user_name, rc);
5510                }
5511            }
5512        }
5513    }
5514
5515  if(!ActiveDirectory)
5516    {
5517      if (rc = moira_connect())
5518        {
5519          critical_alert(whoami, "Ldap incremental",
5520                         "Error contacting Moira server : %s",
5521                         error_message(rc));
5522          return;
5523        }
5524 
5525      argv[0] = filesys_name;
5526
5527      if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info,
5528                          save_argv)))
5529        {
5530          n = 0;
5531          ADD_ATTR("mitMoiraIMAPAddress", mit_moira_imap_address_v,
5532                   LDAP_MOD_REPLACE);
5533          mods[n] = NULL;
5534          rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5535         
5536          if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
5537            rc = LDAP_SUCCESS;
5538
5539          if(rc)
5540            com_err(whoami, 0,
5541                    "Unable to set the mitMoiraIMAPAddress for %s : %s",
5542                    user_name, ldap_err2string(rc));
5543
5544          sprintf(temp, "%s@%s", user_name, save_argv[FS_MACHINE]);
5545         
5546          mit_moira_imap_address_v[0]  = temp;
5547               
5548          n = 0;
5549          ADD_ATTR("mitMoiraIMAPAddress", mit_moira_imap_address_v,
5550                   LDAP_MOD_ADD);
5551          mods[n] = NULL;
5552          rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5553         
5554          if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
5555            rc = LDAP_SUCCESS;
5556         
5557          if(rc)
5558            com_err(whoami, 0, "Unable to set the mitMoiraIMAPAddress for "
5559                    "%s : %s", user_name, ldap_err2string(rc));   
5560        } else if(rc==MR_NO_MATCH) {
5561         
5562          n = 0;
5563          ADD_ATTR("mitMoiraIMAPAddress", mit_moira_imap_address_v,
5564                   LDAP_MOD_REPLACE);
5565          mods[n] = NULL;
5566          rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5567         
5568          if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
5569            rc = LDAP_SUCCESS;
5570
5571          if(rc)
5572            com_err(whoami, 0,
5573                    "Unable to set the mitMoiraIMAPAddress for %s : %s",
5574                    user_name, ldap_err2string(rc));
5575
5576        }
5577
5578      argv[0] = user_name;
5579   
5580      if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
5581        {
5582          n = 0;
5583          ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_REPLACE);
5584          mods[n] = NULL;
5585          rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5586           
5587          if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
5588            rc = LDAP_SUCCESS;
5589
5590          if(rc)
5591            com_err(whoami, 0,
5592                    "Unable to set the mailRoutingAddress for %s : %s",
5593                    user_name, ldap_err2string(rc));
5594
5595          p = strdup(save_argv[3]);
5596         
5597          if((c = strchr(p, ',')) != NULL) {
5598            q = strtok(p, ",");
5599            StringTrim(q);
5600
5601            if ((c = strchr(q, '@')) == NULL)
5602              sprintf(temp, "%s@mit.edu", q);
5603            else
5604              sprintf(temp, "%s", q);
5605
5606            if(email_isvalid(temp) && atoi(av[U_STATE]) != US_DELETED)
5607              {
5608                mail_routing_v[0]  = temp;
5609
5610                n = 0;
5611                ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
5612                mods[n] = NULL;
5613                rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5614               
5615                if (rc == LDAP_ALREADY_EXISTS ||
5616                    rc == LDAP_TYPE_OR_VALUE_EXISTS)
5617                  rc = LDAP_SUCCESS;
5618               
5619                if(rc)
5620                  com_err(whoami, 0,
5621                          "Unable to set the mailRoutingAddress for %s : %s",
5622                          user_name, ldap_err2string(rc));
5623              }
5624
5625            while((q = strtok(NULL, ",")) != NULL) {
5626              StringTrim(q);
5627
5628              if((c = strchr(q, '@')) == NULL)
5629                sprintf(temp, "%s@mit.edu", q);
5630              else
5631                sprintf(temp, "%s", q);
5632
5633              if(email_isvalid(temp) && atoi(av[U_STATE]) != US_DELETED)
5634                {
5635                  mail_routing_v[0]  = temp;
5636                 
5637                  n = 0;
5638                  ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
5639                  mods[n] = NULL;
5640                  rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5641                 
5642                  if (rc == LDAP_ALREADY_EXISTS ||
5643                      rc == LDAP_TYPE_OR_VALUE_EXISTS)
5644                    rc = LDAP_SUCCESS;
5645                 
5646                  if(rc)
5647                    com_err(whoami, 0,
5648                            "Unable to set the mailRoutingAddress for %s : %s",
5649                            user_name, ldap_err2string(rc));
5650                }
5651            }
5652          } else {
5653            StringTrim(p);
5654
5655            if((c = strchr(p, '@')) == NULL)
5656              sprintf(temp, "%s@mit.edu", p);
5657            else
5658              sprintf(temp, "%s", p);
5659
5660            if(email_isvalid(temp) && atoi(av[U_STATE]) != US_DELETED)
5661              {
5662                mail_routing_v[0]  = temp;
5663               
5664                n = 0;
5665                ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
5666                mods[n] = NULL;
5667                rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5668               
5669                if (rc == LDAP_ALREADY_EXISTS ||
5670                    rc == LDAP_TYPE_OR_VALUE_EXISTS)
5671                  rc = LDAP_SUCCESS;
5672               
5673                if(rc)
5674                  com_err(whoami, 0,
5675                          "Unable to set the mailRoutingAddress for %s : %s",
5676                          user_name, ldap_err2string(rc));
5677              }
5678          }
5679        }
5680      moira_disconnect();
5681    }
5682
5683  return(0);
5684}
5685
5686int user_change_status(LDAP *ldap_handle, char *dn_path,
5687                       char *user_name, char *MoiraId,
5688                       int operation)
5689{
5690  char      filter[128];
5691  char      *attr_array[3];
5692  char      temp[256];
5693  char      distinguished_name[1024];
5694  char      **modvalues;
5695  char      *mitMoiraId_v[] = {NULL, NULL};
5696  LDAPMod   *mods[20];
5697  LK_ENTRY  *group_base;
5698  int       group_count;
5699  int       rc;
5700  int       i;
5701  int       n;
5702  ULONG     ulongValue;
5703
5704  if (!check_string(user_name))
5705    {
5706      com_err(whoami, 0, "Unable to process invalid LDAP user name %s",
5707              user_name);
5708      return(AD_INVALID_NAME);
5709    }
5710
5711  group_count = 0;
5712  group_base = NULL;
5713
5714  if (strlen(MoiraId) != 0)
5715    {
5716      sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
5717      attr_array[0] = "UserAccountControl";
5718      attr_array[1] = NULL;
5719      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
5720                               &group_base, &group_count,
5721                               LDAP_SCOPE_SUBTREE)) != 0)
5722        {
5723          com_err(whoami, 0, "Unable to process user %s : %s",
5724                  user_name, ldap_err2string(rc));
5725          return(rc);
5726        }
5727    }
5728
5729  if (group_count != 1)
5730    {
5731      linklist_free(group_base);
5732      group_count = 0;
5733      group_base = NULL;
5734      sprintf(filter, "(sAMAccountName=%s)", user_name);
5735      attr_array[0] = "UserAccountControl";
5736      attr_array[1] = NULL;
5737      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
5738                               &group_base, &group_count,
5739                               LDAP_SCOPE_SUBTREE)) != 0)
5740        {
5741          com_err(whoami, 0, "Unable to process user %s : %s",
5742                  user_name, ldap_err2string(rc));
5743          return(rc);
5744        }
5745    }
5746 
5747  if (group_count != 1)
5748    {
5749      linklist_free(group_base);
5750      com_err(whoami, 0, "Unable to find user %s in directory",
5751              user_name);
5752      return(LDAP_NO_SUCH_OBJECT);
5753    }
5754
5755  strcpy(distinguished_name, group_base->dn);
5756  ulongValue = atoi((*group_base).value);
5757
5758  if (operation == MEMBER_DEACTIVATE)
5759    ulongValue |= UF_ACCOUNTDISABLE;
5760  else   
5761    ulongValue &= ~UF_ACCOUNTDISABLE;
5762
5763  sprintf(temp, "%ld", ulongValue);
5764
5765  if ((rc = construct_newvalues(group_base, group_count, (*group_base).value,
5766                                temp, &modvalues, REPLACE)) == 1)
5767    goto cleanup;
5768
5769  linklist_free(group_base);
5770  group_base = NULL;
5771  group_count = 0;
5772  n = 0;
5773  ADD_ATTR("UserAccountControl", modvalues, LDAP_MOD_REPLACE);
5774
5775  if (strlen(MoiraId) != 0)
5776    {
5777    mitMoiraId_v[0] = MoiraId;
5778    ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
5779    }
5780
5781  mods[n] = NULL;
5782  rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
5783
5784  for (i = 0; i < n; i++)
5785    free(mods[i]);
5786
5787  free_values(modvalues);
5788
5789  if (rc != LDAP_SUCCESS)
5790    {
5791      com_err(whoami, 0, "Unable to change status of user %s : %s",
5792              user_name, ldap_err2string(rc));
5793    }
5794 
5795 cleanup:
5796  return(rc);
5797}
5798
5799int user_delete(LDAP *ldap_handle, char *dn_path,
5800                char *u_name, char *MoiraId)
5801{
5802  char      filter[128];
5803  char      *attr_array[3];
5804  char      distinguished_name[1024];
5805  char      user_name[512];
5806  LK_ENTRY  *group_base;
5807  int       group_count;
5808  int       rc;
5809  char      temp[256];
5810
5811  if (!check_string(u_name))
5812    return(AD_INVALID_NAME);
5813
5814  strcpy(user_name, u_name);
5815  group_count = 0;
5816  group_base = NULL;
5817
5818  if (strlen(MoiraId) != 0)
5819    {
5820      sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
5821      attr_array[0] = "name";
5822      attr_array[1] = NULL;
5823      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
5824                               &group_base, &group_count,
5825                               LDAP_SCOPE_SUBTREE)) != 0)
5826        {
5827          com_err(whoami, 0, "Unable to process user %s : %s",
5828                  user_name, ldap_err2string(rc));
5829          goto cleanup;
5830        }
5831    }
5832 
5833  if (group_count != 1)
5834    {
5835      linklist_free(group_base);
5836      group_count = 0;
5837      group_base = NULL;
5838      sprintf(filter, "(sAMAccountName=%s)", user_name);
5839      attr_array[0] = "name";
5840      attr_array[1] = NULL;
5841      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
5842                               &group_base, &group_count,
5843                               LDAP_SCOPE_SUBTREE)) != 0)
5844        {
5845          com_err(whoami, 0, "Unable to process user %s : %s",
5846                  user_name, ldap_err2string(rc));
5847          goto cleanup;
5848        }
5849    }
5850
5851  if (group_count != 1)
5852    {
5853      goto cleanup;
5854    }
5855 
5856  strcpy(distinguished_name, group_base->dn);
5857
5858  if (rc = ldap_delete_s(ldap_handle, distinguished_name))
5859    {
5860      com_err(whoami, 0, "Unable to process user %s : %s",
5861              user_name, ldap_err2string(rc));
5862    }
5863
5864  /* Need to add code to delete mit.edu contact */
5865
5866  if (Exchange)
5867    {
5868      sprintf(temp, "cn=%s@exchange-forwarding.mit.edu,%s,%s", user_name,
5869              contact_ou, dn_path);
5870
5871      if(rc = ldap_delete_s(ldap_handle, temp))
5872        {
5873          com_err(whoami, 0, "Unable to delete user contact for %s",
5874                  user_name);
5875        }
5876    }
5877
5878 cleanup:
5879  linklist_free(group_base);
5880
5881  return(0);
5882}
5883
5884void linklist_free(LK_ENTRY *linklist_base)
5885{
5886  LK_ENTRY *linklist_previous;
5887
5888  while (linklist_base != NULL)
5889    {
5890      if (linklist_base->dn != NULL)
5891        free(linklist_base->dn);
5892
5893      if (linklist_base->attribute != NULL)
5894        free(linklist_base->attribute);
5895
5896      if (linklist_base->value != NULL)
5897        free(linklist_base->value);
5898
5899      if (linklist_base->member != NULL)
5900        free(linklist_base->member);
5901
5902      if (linklist_base->type != NULL)
5903        free(linklist_base->type);
5904
5905      if (linklist_base->list != NULL)
5906        free(linklist_base->list);
5907
5908      linklist_previous = linklist_base;
5909      linklist_base = linklist_previous->next;
5910      free(linklist_previous);
5911    }
5912}
5913
5914void free_values(char **modvalues)
5915{
5916  int i;
5917
5918  i = 0;
5919
5920  if (modvalues != NULL)
5921    {
5922    while (modvalues[i] != NULL)
5923      {
5924        free(modvalues[i]);
5925        modvalues[i] = NULL;
5926        ++i;
5927      }
5928    free(modvalues);
5929  }
5930}
5931
5932static int illegalchars[] = {
5933  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
5934  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
5935  1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */
5936  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
5937  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
5938  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
5939  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
5940  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
5941  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5942  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5943  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5944  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5945  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5946  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5947  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5948  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5949};
5950
5951static int illegalchars_ldap[] = {
5952  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
5953  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
5954  0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* SPACE - / */
5955  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */
5956  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
5957  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, /* P - _ */
5958  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
5959  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
5960  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5961  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5962  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5963  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5964  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5965  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5966  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5967  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5968};
5969
5970int check_string(char *s)
5971{
5972  char  character;
5973  char  *string;
5974
5975  string = s;
5976
5977  for (; *s; s++)
5978    {
5979      character = *s;
5980
5981      if (isupper(character))
5982        character = tolower(character);
5983
5984      if(ActiveDirectory)
5985        {
5986          if (illegalchars[(unsigned) character])
5987            {
5988              com_err(whoami, 0, "Found illegal char '%c' (%d) in string %s",
5989                      character, (unsigned) character, string);
5990              return 0;
5991            }
5992        }
5993      else
5994        {
5995          if (illegalchars_ldap[(unsigned) character])
5996            {
5997              com_err(whoami, 0, "Found illegal char '%c' (%d) in string %s",
5998                      character, (unsigned) character, string);
5999              return 0;
6000            }
6001        }
6002    }
6003
6004  return(1);
6005}
6006
6007int check_container_name(char *s)
6008{
6009  char  character;
6010
6011  for (; *s; s++)
6012    {
6013      character = *s;
6014
6015      if (isupper(character))
6016        character = tolower(character);
6017
6018      if (character == ' ')
6019        continue;
6020
6021      if (illegalchars[(unsigned) character])
6022        return 0;
6023    }
6024
6025  return(1);
6026}
6027
6028int mr_connect_cl(char *server, char *client, int version, int auth)
6029{
6030  int   status;
6031  char  *motd;
6032  char  temp[128];
6033
6034  status = mr_connect(server);
6035
6036  if (status)
6037    {
6038      com_err(whoami, status, "while connecting to Moira");
6039      return status;
6040    }
6041
6042  status = mr_motd(&motd);
6043
6044  if (status)
6045    {
6046      mr_disconnect();
6047      com_err(whoami, status, "while checking server status");
6048      return status;
6049    }
6050
6051  if (motd)
6052    {
6053      sprintf(temp, "The Moira server is currently unavailable: %s", motd);
6054      com_err(whoami, status, temp);
6055      mr_disconnect();
6056      return status;
6057    }
6058
6059  status = mr_version(version);
6060
6061  if (status)
6062    {
6063      if (status == MR_UNKNOWN_PROC)
6064        {
6065          if (version > 2)
6066            status = MR_VERSION_HIGH;
6067          else
6068            status = MR_SUCCESS;
6069        }
6070
6071      if (status == MR_VERSION_HIGH)
6072        {
6073          com_err(whoami, 0, "Warning: This client is running newer code "
6074                  "than the server.");
6075                  com_err(whoami, 0, "Some operations may not work.");
6076        }
6077      else if (status && status != MR_VERSION_LOW)
6078        {
6079          com_err(whoami, status, "while setting query version number.");
6080          mr_disconnect();
6081          return status;
6082        }
6083    }
6084
6085  if (auth)
6086    {
6087      status = mr_krb5_auth(client);
6088      if (status)
6089        {
6090          com_err(whoami, status, "while authenticating to Moira.");
6091          mr_disconnect();
6092          return status;
6093        }
6094    }
6095 
6096  return MR_SUCCESS;
6097}
6098
6099void AfsToWinAfs(char* path, char* winPath)
6100{
6101  char* pathPtr;
6102  char* winPathPtr;
6103  strcpy(winPath, WINAFS);
6104  pathPtr = path + strlen(AFS);
6105  winPathPtr = winPath + strlen(WINAFS);
6106 
6107  while (*pathPtr)
6108    {
6109      if (*pathPtr == '/')
6110        *winPathPtr = '\\';
6111      else
6112        *winPathPtr = *pathPtr;
6113     
6114      pathPtr++;
6115      winPathPtr++;
6116    }
6117}
6118
6119int GetAceInfo(int ac, char **av, void *ptr)
6120{
6121  char **call_args;
6122  int   security_flag;
6123
6124  call_args = ptr;
6125 
6126  strcpy(call_args[0], av[L_ACE_TYPE]);
6127  strcpy(call_args[1], av[L_ACE_NAME]);
6128  security_flag = 0;
6129  get_group_membership(call_args[2], call_args[3], &security_flag, av);
6130  return(LDAP_SUCCESS); 
6131}
6132
6133int checkADname(LDAP *ldap_handle, char *dn_path, char *Name)
6134{
6135  char filter[128];
6136  char *attr_array[3];
6137  int  group_count;
6138  int  rc;
6139  LK_ENTRY  *group_base;
6140 
6141  group_count = 0;
6142  group_base = NULL;
6143 
6144  sprintf(filter, "(sAMAccountName=%s)", Name);
6145  attr_array[0] = "sAMAccountName";
6146  attr_array[1] = NULL;
6147
6148  if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
6149                           &group_base, &group_count,
6150                           LDAP_SCOPE_SUBTREE)) != 0)
6151    {
6152      com_err(whoami, 0, "Unable to process ACE name %s : %s",
6153              Name, ldap_err2string(rc));
6154      return(1);
6155    }
6156
6157  linklist_free(group_base);
6158  group_base = NULL;
6159
6160  if (group_count == 0)
6161    return(0);
6162 
6163  return(1);
6164}
6165
6166#define MAX_ACE 7
6167
6168int ProcessAce(LDAP *ldap_handle, char *dn_path, char *Name, char *Type,
6169               int UpdateGroup, int *ProcessGroup, char *maillist,
6170               char *nfsgroup)
6171{
6172  char  *av[2];
6173  char  GroupName[256];
6174  char  *call_args[7];
6175  int   rc;
6176  char  *AceInfo[4];
6177  char  AceType[32];
6178  char  AceName[128];
6179  char  AceMembership[2];
6180  char  AceOu[256];
6181  char  temp[128];
6182  char  *save_argv[U_END];
6183
6184  if (!SetGroupAce)
6185    {
6186      com_err(whoami, 0, "ProcessAce disabled, skipping");
6187      return(0);
6188    }
6189
6190  strcpy(GroupName, Name);
6191 
6192  if (strcasecmp(Type, "LIST"))
6193    return(1);
6194
6195  while (1)
6196    {
6197      av[0] = GroupName;
6198      AceInfo[0] = AceType;
6199      AceInfo[1] = AceName;
6200      AceInfo[2] = AceMembership;
6201      AceInfo[3] = AceOu;
6202      memset(AceType, '\0', sizeof(AceType));
6203      memset(AceName, '\0', sizeof(AceName));
6204      memset(AceMembership, '\0', sizeof(AceMembership));
6205      memset(AceOu, '\0', sizeof(AceOu));
6206      callback_rc = 0;
6207   
6208      if (rc = mr_query("get_list_info", 1, av, GetAceInfo, AceInfo))
6209        {
6210          if(rc != MR_NO_MATCH)
6211            com_err(whoami, 0, "Unable to get ACE info for list %s : %s",
6212                    GroupName, error_message(rc));
6213
6214          return(1);
6215        }
6216
6217      if (callback_rc)
6218        {
6219          com_err(whoami, 0, "Unable to get ACE info for list %s", GroupName);
6220          return(1);
6221        }
6222
6223      if ((strcasecmp(AceType, "USER")) && (strcasecmp(AceType, "LIST")))
6224        return(0);
6225
6226      strcpy(temp, AceName);
6227
6228      if (!strcasecmp(AceType, "LIST"))
6229        sprintf(temp, "%s%s", AceName, group_suffix);
6230
6231      if (!UpdateGroup)
6232        {
6233          if (checkADname(ldap_handle, dn_path, temp))
6234              return(0);
6235
6236          (*ProcessGroup) = 1;
6237        }
6238
6239      if (!strcasecmp(AceInfo[0], "LIST"))
6240        {
6241          if (make_new_group(ldap_handle, dn_path, "", AceName, AceOu,
6242                             AceMembership, 0, UpdateGroup, maillist,
6243                             nfsgroup))
6244            return(1);
6245
6246          populate_group(ldap_handle, dn_path, AceName, AceOu, AceMembership,
6247                         0, "", 1);
6248        }
6249      else if (!strcasecmp(AceInfo[0], "USER"))
6250        {
6251          av[0] = AceName;
6252          call_args[0] = (char *)ldap_handle;
6253          call_args[1] = dn_path;
6254          call_args[2] = "";
6255          call_args[3] = NULL;
6256          callback_rc = 0;
6257
6258          if(!strcasecmp(AceName, PRODUCTION_PRINCIPAL) ||
6259             !strcasecmp(AceName, TEST_PRINCIPAL))
6260            {
6261              return(1);
6262            }
6263
6264          if (rc = mr_query("get_user_account_by_login", 1, av,
6265                            save_query_info, save_argv))
6266            {
6267              com_err(whoami, 0, "Unable to process user ACE %s for group %s.",
6268                      AceName, Name);
6269              return(1);
6270            }
6271
6272          if (rc = user_create(U_END, save_argv, call_args))
6273            {
6274              com_err(whoami, 0, "Unable to process user ACE %s for group %s.",
6275                      AceName, Name);
6276              return(1);
6277            }
6278         
6279          if (callback_rc)
6280            {
6281              com_err(whoami, 0, "Unable to process user Ace %s for group %s",
6282                      AceName, Name);
6283              return(1);
6284            }
6285
6286          return(0);
6287        }
6288      else
6289        return(1);
6290
6291      if (!strcasecmp(AceType, "LIST"))
6292        {
6293          if (!strcasecmp(GroupName, AceName))
6294            return(0);
6295        }
6296
6297      strcpy(GroupName, AceName);
6298    }
6299 
6300  return(1);
6301}
6302
6303int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId,
6304                   char *group_name, char *group_ou, char *group_membership,
6305                   int group_security_flag, int updateGroup, char *maillist,
6306                   char *nfsgroup)
6307{
6308  char  *av[3];
6309  char  *call_args[8];
6310  int   rc;
6311  LK_ENTRY  *group_base;
6312  int  group_count;
6313  char filter[128];
6314  char *attr_array[3];
6315
6316  av[0] = group_name;
6317  call_args[0] = (char *)ldap_handle;
6318  call_args[1] = dn_path;
6319  call_args[2] = group_name;
6320  call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
6321  call_args[4] = (char *)(long)updateGroup;
6322  call_args[5] = MoiraId;
6323  call_args[6] = "0";
6324  call_args[7] = NULL;
6325  callback_rc = 0;
6326
6327  group_count = 0;
6328  group_base = NULL;
6329
6330  if (rc = mr_query("get_list_info", 1, av, group_create, call_args))
6331    {
6332      moira_disconnect();
6333      com_err(whoami, 0, "Unable to create list %s : %s", group_name,
6334              error_message(rc));
6335      return(rc);
6336    }
6337
6338  if (callback_rc)
6339    {
6340      moira_disconnect();
6341      com_err(whoami, 0, "Unable to create list %s", group_name);
6342      return(callback_rc);
6343    }
6344
6345  return(0);
6346}
6347
6348int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name,
6349                   char *group_ou, char *group_membership,
6350                   int group_security_flag, char *MoiraId,
6351                   int synchronize)
6352{
6353  char      *av[3];
6354  char      *call_args[7];
6355  char      *pUserOu;
6356  LK_ENTRY  *ptr;
6357  int       rc;
6358  char      member[512];
6359  char      *s;
6360  char      **members;
6361  int       i = 0;
6362  int       j = 0;
6363  int       n = 0;
6364  char      group_dn[512];
6365  LDAPMod   *mods[20];
6366  char      *member_v[] = {NULL, NULL};
6367  char      *save_argv[U_END];
6368  char      machine_ou[256];
6369  char      NewMachineName[1024];
6370
6371  com_err(whoami, 0, "Populating group %s", group_name);
6372  av[0] = group_name;
6373  call_args[0] = (char *)ldap_handle;
6374  call_args[1] = dn_path;
6375  call_args[2] = group_name;
6376  call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS |
6377                          MOIRA_MACHINE);
6378  call_args[4] = NULL;
6379  member_base = NULL;
6380  group_members = 0;
6381
6382  if((max_group_members == -1) && !synchronize) {
6383    com_err(whoami, 0, "Skipping populate group for %s", group_name);
6384    return(0);
6385  }
6386
6387  if (rc = mr_query("get_end_members_of_list", 1, av,
6388                    member_list_build, call_args))
6389    {
6390      if(rc == MR_LIST)
6391        return(0);
6392     
6393      com_err(whoami, 0, "Unable to populate list %s : %s",
6394              group_name, error_message(rc));
6395      return(3);
6396    }
6397
6398  if (member_base != NULL)
6399    {
6400      ptr = member_base;
6401
6402      while(ptr != NULL)
6403        {
6404          if (!strcasecmp(ptr->type, "LIST"))
6405            {
6406              ptr = ptr->next;
6407              continue;
6408            }
6409
6410          if (!strcasecmp(ptr->type, "MACHINE") && !ProcessMachineContainer)
6411            {
6412              ptr = ptr->next;
6413              continue;
6414            }
6415
6416          if(!strcasecmp(ptr->type, "USER"))
6417            {
6418              if(!strcasecmp(ptr->member, PRODUCTION_PRINCIPAL) ||
6419                 !strcasecmp(ptr->member, TEST_PRINCIPAL))
6420                {
6421                  ptr = ptr->next;
6422                  continue;
6423                }
6424            }
6425
6426          ptr = ptr->next;
6427          group_members++;
6428        }
6429    }
6430
6431  if(max_group_members && !synchronize && (group_members > max_group_members))
6432    {
6433      com_err(whoami, 0,
6434              "Group %s membership of %d exceeds maximum %d, skipping",
6435              group_name, group_members, max_group_members);
6436      return(0);
6437    }
6438
6439  members = (char **)malloc(sizeof(char *) * 2);
6440
6441  if (member_base != NULL)
6442    {
6443      ptr = member_base;
6444
6445      while (ptr != NULL)
6446        {
6447          if (!strcasecmp(ptr->type, "LIST"))
6448            {
6449              ptr = ptr->next;
6450              continue;
6451            }
6452         
6453          if (!strcasecmp(ptr->type, "MACHINE") && !ProcessMachineContainer)
6454            {
6455              ptr = ptr->next;
6456              continue;
6457            }
6458           
6459          if(!strcasecmp(ptr->type, "USER"))
6460            {
6461              if(!strcasecmp(ptr->member, PRODUCTION_PRINCIPAL) ||
6462                 !strcasecmp(ptr->member, TEST_PRINCIPAL))
6463                {
6464                  ptr = ptr->next;
6465                  continue;
6466                }
6467
6468              if ((rc = check_user(ldap_handle, dn_path, ptr->member,
6469                                   "")) == AD_NO_USER_FOUND)
6470                {
6471                  com_err(whoami, 0, "creating user %s", ptr->member);
6472
6473                  av[0] = ptr->member;
6474                  call_args[0] = (char *)ldap_handle;
6475                  call_args[1] = dn_path;
6476                  call_args[2] = "";
6477                  call_args[3] = NULL;
6478                  callback_rc = 0;
6479                 
6480                  if (rc = mr_query("get_user_account_by_login", 1, av,
6481                                    save_query_info, save_argv))
6482                    {
6483                      com_err(whoami, 0, "Unable to create user %s "
6484                              "while populating group %s.", ptr->member,
6485                              group_name);
6486
6487                      return(3);
6488                    }
6489
6490                  if (rc = user_create(U_END, save_argv, call_args))
6491                    {
6492                      com_err(whoami, 0, "Unable to create user %s "
6493                              "while populating group %s.", ptr->member,
6494                              group_name);
6495                     
6496                      return(3);
6497                    }
6498         
6499                  if (callback_rc)
6500                    {
6501                      com_err(whoami, 0, "Unable to create user %s "
6502                              "while populating group %s", ptr->member,
6503                              group_name);
6504
6505                      return(3);
6506                    }
6507                }
6508
6509              pUserOu = user_ou;
6510                 
6511              if(ActiveDirectory)
6512                {
6513                  sprintf(member, "cn=%s,%s,%s", ptr->member, pUserOu,
6514                          dn_path);
6515                }
6516              else
6517                {
6518                  sprintf(member, "uid=%s,%s,%s", ptr->member, pUserOu,
6519                          dn_path);
6520                }
6521            }
6522          else if (!strcasecmp(ptr->type, "STRING"))
6523            {
6524              if (contact_create(ldap_handle, dn_path, ptr->member,
6525                                 contact_ou))
6526                return(3);
6527
6528              pUserOu = contact_ou;
6529              sprintf(member, "cn=%s,%s,%s", escape_string(ptr->member),
6530                      pUserOu, dn_path);
6531            }
6532          else if (!strcasecmp(ptr->type, "KERBEROS"))
6533            {
6534              if (contact_create(ldap_handle, dn_path, ptr->member,
6535                                 kerberos_ou))
6536                return(3);
6537
6538              pUserOu = kerberos_ou;
6539              sprintf(member, "cn=%s,%s,%s", escape_string(ptr->member),
6540                      pUserOu, dn_path);
6541            }
6542          else if (!strcasecmp(ptr->type, "MACHINE"))
6543            {
6544              memset(machine_ou, '\0', sizeof(machine_ou));
6545              memset(NewMachineName, '\0', sizeof(NewMachineName));
6546
6547              if (!get_machine_ou(ldap_handle, dn_path, ptr->member,
6548                                 machine_ou, NewMachineName))
6549                {
6550                  pUserOu = machine_ou;
6551                  sprintf(member, "cn=%s,%s,%s", NewMachineName, pUserOu,
6552                          dn_path);
6553                }
6554              else
6555                {
6556                  ptr = ptr->next;                 
6557                  continue;
6558                }
6559            }
6560
6561          if(i > 1)
6562            members = (char **)realloc(members, ((i + 2) * sizeof(char *)));
6563          members[i++] = strdup(member);
6564
6565          ptr = ptr->next;
6566        }
6567   
6568      linklist_free(member_base);
6569      member_base = NULL;
6570    }
6571
6572  members[i] = NULL;
6573
6574  sprintf(group_dn, "cn=%s,%s,%s", group_name, group_ou, dn_path);
6575
6576  if(GroupPopulateDelete)
6577    {
6578      n = 0;
6579      ADD_ATTR("member", member_v, LDAP_MOD_REPLACE);
6580      mods[n] = NULL;
6581     
6582      if ((rc = ldap_modify_s(ldap_handle, group_dn,
6583                              mods)) != LDAP_SUCCESS)
6584        {
6585          com_err(whoami, 0,
6586                  "Unable to populate group membership for %s: %s",
6587                  group_dn, ldap_err2string(rc));
6588        }
6589 
6590      for (i = 0; i < n; i++)
6591        free(mods[i]);
6592    }
6593
6594  n = 0;
6595  ADD_ATTR("member", members, LDAP_MOD_REPLACE);
6596  mods[n] = NULL;
6597
6598  if ((rc = ldap_modify_s(ldap_handle, group_dn,
6599                          mods)) != LDAP_SUCCESS)
6600    {
6601      com_err(whoami, 0,
6602              "Unable to populate group membership for %s: %s",
6603              group_dn, ldap_err2string(rc));
6604    }
6605 
6606  for (i = 0; i < n; i++)
6607    free(mods[i]);
6608   
6609  free(members);
6610
6611  return(0);
6612}
6613
6614int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId,
6615                  char *group_name, char *group_ou, char *group_membership,
6616                  int group_security_flag, int type, char *maillist,
6617                  char *nfsgroup)
6618{
6619  char      before_desc[512];
6620  char      before_name[256];
6621  char      before_group_ou[256];
6622  char      before_group_membership[2];
6623  char      distinguishedName[256];
6624  char      ad_distinguishedName[256];
6625  char      filter[128];
6626  char      *attr_array[3];
6627  int       before_security_flag;
6628  int       group_count;
6629  int       rc;
6630  LK_ENTRY  *group_base;
6631  LK_ENTRY  *ptr;
6632  char      ou_both[512];
6633  char      ou_security[512];
6634  char      ou_distribution[512];
6635  char      ou_neither[512];
6636  char      group_dn[512];
6637
6638  memset(ad_distinguishedName, '\0', sizeof(ad_distinguishedName));
6639  sprintf(distinguishedName, "CN=%s,%s,%s", group_name, group_ou, dn_path);
6640
6641  memset(filter, '\0', sizeof(filter));
6642  group_base = NULL;
6643  group_count = 0;
6644
6645  if (rc = ad_get_group(ldap_handle, dn_path, group_name,
6646                        "*", MoiraId,
6647                        "samAccountName", &group_base,
6648                        &group_count, filter))
6649    return(rc);
6650
6651  if (type == CHECK_GROUPS)
6652    {
6653      if (group_count == 1)
6654        {
6655          strcpy(group_dn, group_base->dn);
6656
6657          if (!strcasecmp(group_dn, distinguishedName))
6658            {
6659              linklist_free(group_base);
6660              return(0);
6661            }
6662        }
6663
6664      linklist_free(group_base);
6665
6666      if (group_count == 0)
6667        return(AD_NO_GROUPS_FOUND);
6668
6669      if (group_count == 1)
6670        return(AD_WRONG_GROUP_DN_FOUND);
6671
6672      return(AD_MULTIPLE_GROUPS_FOUND);
6673    }
6674
6675  if (group_count == 0)
6676    {
6677      return(AD_NO_GROUPS_FOUND);
6678    }
6679
6680  if (group_count > 1)
6681    {
6682      ptr = group_base;
6683
6684      strcpy(group_dn, ptr->dn);
6685
6686      while (ptr != NULL)
6687        {
6688          if (!strcasecmp(group_dn, ptr->value))
6689            break;
6690
6691          ptr = ptr->next;
6692        }
6693
6694      if (ptr == NULL)
6695        {
6696          com_err(whoami, 0, "%d groups with moira id = %s", group_count,
6697                  MoiraId);
6698          ptr = group_base;
6699
6700          while (ptr != NULL)
6701            {
6702              com_err(whoami, 0, "%s with moira id = %s", ptr->value, MoiraId);
6703              ptr = ptr->next;
6704            }
6705
6706          linklist_free(group_base);
6707          return(AD_MULTIPLE_GROUPS_FOUND);
6708        }
6709
6710      ptr = group_base;
6711
6712      while (ptr != NULL)
6713        {
6714          strcpy(group_dn, ptr->dn);
6715
6716          if (strcasecmp(group_dn, ptr->value))
6717            rc = ldap_delete_s(ldap_handle, ptr->value);
6718
6719          ptr = ptr->next;
6720        }
6721
6722      linklist_free(group_base);
6723      memset(filter, '\0', sizeof(filter));
6724      group_base = NULL;
6725      group_count = 0;
6726
6727      if (rc = ad_get_group(ldap_handle, dn_path, group_name,
6728                            "*", MoiraId,
6729                            "samAccountName", &group_base,
6730                            &group_count, filter))
6731        return(rc);
6732
6733      if (group_count == 0)
6734        return(AD_NO_GROUPS_FOUND);
6735
6736      if (group_count > 1)
6737        return(AD_MULTIPLE_GROUPS_FOUND);
6738    }
6739
6740  strcpy(ad_distinguishedName, group_base->dn);
6741  linklist_free(group_base);
6742  group_base = NULL;
6743  group_count = 0;
6744
6745  attr_array[0] = "sAMAccountName";
6746  attr_array[1] = NULL;
6747 
6748  if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
6749                           &group_base, &group_count,
6750                           LDAP_SCOPE_SUBTREE)) != 0)
6751    {
6752      com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6753              MoiraId, ldap_err2string(rc));
6754      return(rc);
6755    }
6756 
6757  sprintf(filter, "(sAMAccountName=%s)", group_base->value);
6758
6759  if (!strcasecmp(ad_distinguishedName, distinguishedName))
6760    {
6761      linklist_free(group_base);
6762      group_base = NULL;
6763      group_count = 0;
6764      return(0);
6765    }
6766
6767  linklist_free(group_base);
6768  group_base = NULL;
6769  group_count = 0;
6770  memset(ou_both, '\0', sizeof(ou_both));
6771  memset(ou_security, '\0', sizeof(ou_security));
6772  memset(ou_distribution, '\0', sizeof(ou_distribution));
6773  memset(ou_neither, '\0', sizeof(ou_neither));
6774  memset(before_name, '\0', sizeof(before_name));
6775  memset(before_desc, '\0', sizeof(before_desc));
6776  memset(before_group_membership, '\0', sizeof(before_group_membership));
6777 
6778  attr_array[0] = "name";
6779  attr_array[1] = NULL;
6780
6781  if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
6782                           &group_base, &group_count,
6783                           LDAP_SCOPE_SUBTREE)) != 0)
6784    {
6785      com_err(whoami, 0, "Unable to get list name with MoiraId = %s: %s",
6786              MoiraId, ldap_err2string(rc));
6787      return(rc);
6788    }
6789
6790  strcpy(before_name, group_base->value);
6791  linklist_free(group_base);
6792  group_base = NULL;
6793  group_count = 0;
6794
6795  attr_array[0] = "description";
6796  attr_array[1] = NULL;
6797 
6798  if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
6799                           &group_base, &group_count,
6800                           LDAP_SCOPE_SUBTREE)) != 0)
6801    {
6802      com_err(whoami, 0,
6803              "Unable to get list description with MoiraId = %s: %s",
6804              MoiraId, ldap_err2string(rc));
6805      return(rc);
6806    }
6807
6808  if (group_count != 0)
6809    {
6810      strcpy(before_desc, group_base->value);
6811      linklist_free(group_base);
6812      group_base = NULL;
6813      group_count = 0;
6814    }
6815 
6816  change_to_lower_case(ad_distinguishedName); 
6817  strcpy(ou_both, group_ou_both);
6818  change_to_lower_case(ou_both);
6819  strcpy(ou_security, group_ou_security);
6820  change_to_lower_case(ou_security);
6821  strcpy(ou_distribution, group_ou_distribution);
6822  change_to_lower_case(ou_distribution);
6823  strcpy(ou_neither, group_ou_neither);
6824  change_to_lower_case(ou_neither);
6825
6826  if (strstr(ad_distinguishedName, ou_both))
6827    {
6828      strcpy(before_group_ou, group_ou_both);
6829      before_group_membership[0] = 'B';
6830      before_security_flag = 1;
6831    }
6832  else if (strstr(ad_distinguishedName, ou_security))
6833    {
6834      strcpy(before_group_ou, group_ou_security);
6835      before_group_membership[0] = 'S';
6836      before_security_flag = 1;
6837    }
6838  else if (strstr(ad_distinguishedName, ou_distribution))
6839    {
6840      strcpy(before_group_ou, group_ou_distribution);
6841      before_group_membership[0] = 'D';
6842      before_security_flag = 0;
6843    }
6844  else if (strstr(ad_distinguishedName, ou_neither))
6845    {
6846      strcpy(before_group_ou, group_ou_neither);
6847      before_group_membership[0] = 'N';
6848      before_security_flag = 0;
6849    }
6850  else
6851    return(AD_NO_OU_FOUND);
6852
6853  rc = group_rename(ldap_handle, dn_path, before_name,
6854                    before_group_membership,
6855                    before_group_ou, before_security_flag, before_desc,
6856                    group_name, group_membership, group_ou,
6857                    group_security_flag,
6858                    before_desc, MoiraId, filter, maillist, nfsgroup);
6859
6860  return(rc);
6861}
6862
6863void change_to_lower_case(char *ptr)
6864{
6865  int i;
6866
6867  for (i = 0; i < (int)strlen(ptr); i++)
6868    {
6869      ptr[i] = tolower(ptr[i]);
6870    }
6871}
6872
6873int ad_get_group(LDAP *ldap_handle, char *dn_path,
6874                 char *group_name, char *group_membership,
6875                 char *MoiraId, char *attribute,
6876                 LK_ENTRY **linklist_base, int *linklist_count,
6877                 char *rFilter)
6878{
6879  LK_ENTRY  *pPtr;
6880  char  filter[128];
6881  char  *attr_array[3];
6882  char  *dn;
6883  int   rc;
6884
6885  (*linklist_base) = NULL;
6886  (*linklist_count) = 0;
6887
6888  if (strlen(rFilter) != 0)
6889    {
6890      strcpy(filter, rFilter);
6891      attr_array[0] = attribute;
6892      attr_array[1] = NULL;
6893     
6894      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
6895                               linklist_base, linklist_count,
6896                               LDAP_SCOPE_SUBTREE)) != 0)
6897        {
6898          com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6899                  MoiraId, ldap_err2string(rc));
6900         return(rc);
6901       }
6902
6903    if ((*linklist_count) == 1)
6904      {
6905        strcpy(rFilter, filter);
6906        return(0);
6907      }
6908    }
6909
6910  linklist_free((*linklist_base));
6911  (*linklist_base) = NULL;
6912  (*linklist_count) = 0;
6913
6914  if (strlen(MoiraId) != 0)
6915    {
6916      sprintf(filter, "(&(objectClass=group)(mitMoiraId=%s))", MoiraId);
6917
6918      attr_array[0] = attribute;
6919      attr_array[1] = NULL;
6920
6921      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
6922                               linklist_base, linklist_count,
6923                               LDAP_SCOPE_SUBTREE)) != 0)
6924        {
6925          com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6926                  MoiraId, ldap_err2string(rc));
6927         return(rc);
6928       }
6929    }
6930
6931  if ((*linklist_count) > 1)
6932    {
6933      com_err(whoami, 0, "multiple groups with mitMoiraId = %s", MoiraId);
6934      pPtr = (*linklist_base);
6935
6936      while (pPtr)
6937        {
6938          com_err(whoami, 0, "groups %s has mitMoiraId = %s", pPtr->value,
6939                  MoiraId);
6940          pPtr = pPtr->next;
6941        }
6942
6943      linklist_free((*linklist_base));
6944      (*linklist_base) = NULL;
6945      (*linklist_count) = 0;
6946    }
6947
6948  if ((*linklist_count) == 1)
6949    {
6950
6951      pPtr = (*linklist_base);
6952      dn = strdup(pPtr->dn);
6953      dn += 3;
6954
6955      if (!memcmp(dn, group_name, strlen(group_name)))
6956        {
6957          strcpy(rFilter, filter);
6958          return(0);
6959        }
6960    }
6961
6962  linklist_free((*linklist_base));
6963  (*linklist_base) = NULL;
6964  (*linklist_count) = 0;
6965  sprintf(filter, "(sAMAccountName=%s%s)", group_name, group_suffix);
6966
6967  attr_array[0] = attribute;
6968  attr_array[1] = NULL;
6969
6970  if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
6971                           linklist_base, linklist_count,
6972                           LDAP_SCOPE_SUBTREE)) != 0)
6973    {
6974      com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6975              MoiraId, ldap_err2string(rc));
6976      return(rc);
6977    }
6978
6979  if ((*linklist_count) == 1)
6980    {
6981      strcpy(rFilter, filter);
6982      return(0);
6983    }
6984
6985  return(0);
6986}
6987
6988int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, char *MoiraId)
6989{
6990  char filter[128];
6991  char *attr_array[3];
6992  char SamAccountName[64];
6993  int  group_count;
6994  int  rc;
6995  LK_ENTRY  *group_base;
6996  LK_ENTRY  *gPtr;
6997
6998  group_count = 0;
6999  group_base = NULL;
7000
7001  if (strlen(MoiraId) != 0)
7002    {
7003      sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
7004
7005      attr_array[0] = "sAMAccountName";
7006      attr_array[1] = NULL;
7007      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
7008                               &group_base, &group_count,
7009                               LDAP_SCOPE_SUBTREE)) != 0)
7010        {
7011          com_err(whoami, 0, "Unable to process user %s : %s",
7012                  UserName, ldap_err2string(rc));
7013          return(rc);
7014        }
7015
7016      if (group_count > 1)
7017        {
7018          com_err(whoami, 0, "multiple users exist with MoiraId = %s",
7019                  MoiraId);
7020          gPtr = group_base;
7021
7022          while (gPtr)
7023            {
7024              com_err(whoami, 0, "user %s exist with MoiraId = %s",
7025                      gPtr->value, MoiraId);
7026              gPtr = gPtr->next;
7027            }
7028        }
7029    }
7030
7031  if (group_count != 1)
7032    {
7033      linklist_free(group_base);
7034      group_count = 0;
7035      group_base = NULL;
7036      sprintf(filter, "(sAMAccountName=%s)", UserName);
7037      attr_array[0] = "sAMAccountName";
7038      attr_array[1] = NULL;
7039
7040      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
7041                               &group_base, &group_count,
7042                               LDAP_SCOPE_SUBTREE)) != 0)
7043        {
7044          com_err(whoami, 0, "Unable to process user %s : %s",
7045                  UserName, ldap_err2string(rc));
7046          return(rc);
7047        }
7048    }
7049
7050  if (group_count != 1)
7051    {
7052      linklist_free(group_base);
7053      return(AD_NO_USER_FOUND);
7054    }
7055
7056  strcpy(SamAccountName, group_base->value);
7057  linklist_free(group_base);
7058  group_count = 0;
7059  rc = 0;
7060
7061  if (strcmp(SamAccountName, UserName))
7062    {
7063      com_err(whoami, 0,
7064              "User object %s with MoiraId %s has mismatched usernames "
7065              "(LDAP username %s, Moira username %s)", SamAccountName,
7066              MoiraId, SamAccountName, UserName);
7067    }
7068
7069  return(0);
7070}
7071
7072void container_get_dn(char *src, char *dest)
7073{
7074  char *sPtr;
7075  char *array[20];
7076  char name[256];
7077  int  n;
7078
7079  memset(array, '\0', 20 * sizeof(array[0]));
7080
7081  if (strlen(src) == 0)
7082    return;
7083
7084  strcpy(name, src);
7085  sPtr = name;
7086  n = 0;
7087  array[n] = name;
7088  ++n;
7089
7090  while (*sPtr)
7091    {
7092      if ((*sPtr) == '/')
7093        {
7094          (*sPtr) = '\0';
7095          ++sPtr;
7096          array[n] = sPtr;
7097          ++n;
7098        }
7099      else
7100        ++sPtr;
7101    }
7102
7103  strcpy(dest, "OU=");
7104
7105  while (n != 0)
7106    {
7107      strcat(dest, array[n-1]);
7108      --n;
7109      if (n > 0)
7110        {
7111          strcat(dest, ",OU=");
7112        }
7113    }
7114
7115  return;
7116}
7117
7118void container_get_name(char *src, char *dest)
7119{
7120  char *sPtr;
7121  char *dPtr;
7122
7123  if (strlen(src) == 0)
7124    return;
7125
7126  sPtr = src;
7127  dPtr = src;
7128
7129  while (*sPtr)
7130    {
7131      if ((*sPtr) == '/')
7132        {
7133          dPtr = sPtr;
7134          ++dPtr;
7135        }
7136      ++sPtr;
7137    }
7138
7139  strcpy(dest, dPtr);
7140  return;
7141}
7142
7143void container_check(LDAP *ldap_handle, char *dn_path, char *name)
7144{
7145  char cName[256];
7146  char *av[7];
7147  int  i;
7148  int  rc;
7149
7150  strcpy(cName, name);
7151
7152  for (i = 0; i < (int)strlen(cName); i++)
7153    {
7154      if (cName[i] == '/')
7155        {
7156          cName[i] = '\0';
7157          av[CONTAINER_NAME] = cName;
7158          av[CONTAINER_DESC] = "";
7159          av[CONTAINER_LOCATION] = "";
7160          av[CONTAINER_CONTACT] = "";
7161          av[CONTAINER_TYPE] = "";
7162          av[CONTAINER_ID] = "";
7163          av[CONTAINER_ROWID] = "";
7164          rc = container_create(ldap_handle, dn_path, 7, av);
7165
7166          if (rc == LDAP_SUCCESS)
7167            {
7168              com_err(whoami, 0, "container %s created without a mitMoiraId",
7169                      cName);
7170            }
7171
7172          cName[i] = '/';
7173        }
7174    }
7175}
7176
7177int container_rename(LDAP *ldap_handle, char *dn_path, int beforec,
7178                     char **before, int afterc, char **after)
7179{
7180  char      dName[256];
7181  char      cName[256];
7182  char      new_cn[128];
7183  char      new_dn_path[256];
7184  char      temp[256];
7185  char      distinguishedName[256];
7186  char      *pPtr;
7187  int       rc;
7188  int       i;
7189
7190  memset(cName, '\0', sizeof(cName));
7191  container_get_name(after[CONTAINER_NAME], cName);
7192
7193  if (!check_container_name(cName))
7194    {
7195      com_err(whoami, 0, "Unable to process invalid LDAP container name %s",
7196              cName);
7197      return(AD_INVALID_NAME);
7198    }
7199
7200  memset(distinguishedName, '\0', sizeof(distinguishedName));
7201
7202  if (rc = container_get_distinguishedName(ldap_handle, dn_path,
7203                                           distinguishedName, beforec, before))
7204    return(rc);
7205
7206  if (strlen(distinguishedName) == 0)
7207    {
7208      rc = container_create(ldap_handle, dn_path, afterc, after);
7209      return(rc);
7210    }
7211
7212  strcpy(temp, after[CONTAINER_NAME]);
7213  pPtr = temp;
7214
7215  for (i = 0; i < (int)strlen(temp); i++)
7216    {
7217      if (temp[i] == '/')
7218        {
7219          pPtr = &temp[i];
7220        }
7221    }
7222
7223  (*pPtr) = '\0';
7224
7225  container_get_dn(temp, dName);
7226
7227  if (strlen(temp) != 0)
7228    sprintf(new_dn_path, "%s,%s", dName, dn_path);
7229  else
7230    sprintf(new_dn_path, "%s", dn_path);
7231
7232  sprintf(new_cn, "OU=%s", cName);
7233
7234  container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
7235
7236  if ((rc = ldap_rename_s(ldap_handle, distinguishedName, new_cn, new_dn_path,
7237                          TRUE, NULL, NULL)) != LDAP_SUCCESS)
7238    {
7239      com_err(whoami, 0, "Unable to rename container from %s to %s : %s",
7240              before[CONTAINER_NAME], after[CONTAINER_NAME],
7241              ldap_err2string(rc));
7242      return(rc);
7243    }
7244
7245  memset(dName, '\0', sizeof(dName));
7246  container_get_dn(after[CONTAINER_NAME], dName);
7247  rc = container_adupdate(ldap_handle, dn_path, dName, "", afterc, after);
7248
7249  return(rc);
7250}
7251
7252int container_delete(LDAP *ldap_handle, char *dn_path, int count, char **av)
7253{
7254  char      distinguishedName[256];
7255  int       rc;
7256
7257  memset(distinguishedName, '\0', sizeof(distinguishedName));
7258
7259  if (rc = container_get_distinguishedName(ldap_handle, dn_path,
7260                                           distinguishedName, count, av))
7261    return(rc);
7262
7263  if (strlen(distinguishedName) == 0)
7264    return(0);
7265
7266  if ((rc = ldap_delete_s(ldap_handle, distinguishedName)) != LDAP_SUCCESS)
7267    {
7268      if (rc == LDAP_NOT_ALLOWED_ON_NONLEAF)
7269        container_move_objects(ldap_handle, dn_path, distinguishedName);
7270      else
7271        com_err(whoami, 0, "Unable to delete container %s from directory : %s",
7272                av[CONTAINER_NAME], ldap_err2string(rc));
7273    }
7274
7275  return(rc);
7276}
7277
7278int container_create(LDAP *ldap_handle, char *dn_path, int count, char **av)
7279{
7280  char      *attr_array[3];
7281  LK_ENTRY  *group_base;
7282  int       group_count;
7283  LDAPMod   *mods[20];
7284  char      *objectClass_v[] = {"top",
7285                           "organizationalUnit",
7286                           NULL};
7287
7288  char *ou_v[] = {NULL, NULL};
7289  char *name_v[] = {NULL, NULL};
7290  char *moiraId_v[] = {NULL, NULL};
7291  char *desc_v[] = {NULL, NULL};
7292  char *managedBy_v[] = {NULL, NULL};
7293  char dName[256];
7294  char cName[256];
7295  char managedByDN[256];
7296  char filter[256];
7297  char temp[256];
7298  int  n;
7299  int  i;
7300  int  rc;
7301   
7302  memset(filter, '\0', sizeof(filter));
7303  memset(dName, '\0', sizeof(dName));
7304  memset(cName, '\0', sizeof(cName));
7305  memset(managedByDN, '\0', sizeof(managedByDN));
7306  container_get_dn(av[CONTAINER_NAME], dName);
7307  container_get_name(av[CONTAINER_NAME], cName);
7308
7309  if ((strlen(cName) == 0) || (strlen(dName) == 0))
7310    {
7311      com_err(whoami, 0, "Unable to process invalid LDAP container name %s",
7312              cName);
7313      return(AD_INVALID_NAME);
7314    }
7315
7316  if (!check_container_name(cName))
7317    {
7318      com_err(whoami, 0, "Unable to process invalid LDAP container name %s",
7319              cName);
7320      return(AD_INVALID_NAME);
7321    }
7322
7323  n = 0;
7324  ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
7325  name_v[0] = cName;
7326  ADD_ATTR("name", name_v, LDAP_MOD_ADD);
7327  ou_v[0] = cName;
7328  ADD_ATTR("ou", ou_v, LDAP_MOD_ADD);
7329
7330  if (strlen(av[CONTAINER_ROWID]) != 0)
7331    {
7332      moiraId_v[0] = av[CONTAINER_ROWID];
7333      ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_ADD);
7334    }
7335
7336  if (strlen(av[CONTAINER_DESC]) != 0)
7337    {
7338      desc_v[0] = av[CONTAINER_DESC];
7339      ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
7340    }
7341
7342  if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
7343    {
7344      if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
7345        {
7346          if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID],
7347                              kerberos_ou))
7348            {
7349              sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID],
7350                      kerberos_ou, dn_path);
7351              managedBy_v[0] = managedByDN;
7352              ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
7353            }
7354        }
7355      else
7356        {
7357          if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
7358            {
7359              sprintf(filter, "(&(cn=%s)(&(objectCategory=person)"
7360                      "(objectClass=user)))", av[CONTAINER_ID]);
7361            }
7362
7363          if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
7364            {
7365              sprintf(filter, "(&(objectClass=group)(cn=%s))",
7366                      av[CONTAINER_ID]);
7367            }
7368
7369          if (strlen(filter) != 0)
7370            {
7371              attr_array[0] = "distinguishedName";
7372              attr_array[1] = NULL;
7373              group_count = 0;
7374              group_base = NULL;
7375              if ((rc = linklist_build(ldap_handle, dn_path, filter,
7376                                       attr_array,
7377                                       &group_base, &group_count,
7378                                       LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7379                {
7380                  if (group_count == 1)
7381                    {
7382                      strcpy(managedByDN, group_base->value);
7383                      managedBy_v[0] = managedByDN;
7384                      ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
7385                    }
7386                  linklist_free(group_base);
7387                  group_base = NULL;
7388                  group_count = 0;
7389                }
7390            }
7391        }
7392    }
7393 
7394  mods[n] = NULL;
7395
7396  sprintf(temp, "%s,%s", dName, dn_path);
7397  rc = ldap_add_ext_s(ldap_handle, temp, mods, NULL, NULL);
7398 
7399  for (i = 0; i < n; i++)
7400    free(mods[i]);
7401 
7402  if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
7403    {
7404      com_err(whoami, 0, "Unable to create container %s : %s",
7405              cName, ldap_err2string(rc));
7406      return(rc);
7407    }
7408
7409  if (rc == LDAP_ALREADY_EXISTS)
7410    {
7411      if (strlen(av[CONTAINER_ROWID]) != 0)
7412        rc = container_adupdate(ldap_handle, dn_path, dName, "", count, av);
7413    }
7414
7415  return(rc);
7416}
7417
7418int container_update(LDAP *ldap_handle, char *dn_path, int beforec,
7419                     char **before, int afterc, char **after)
7420{
7421  char distinguishedName[256];
7422  int  rc;
7423
7424  memset(distinguishedName, '\0', sizeof(distinguishedName));
7425
7426  if (rc = container_get_distinguishedName(ldap_handle, dn_path,
7427                                           distinguishedName, afterc, after))
7428    return(rc);
7429
7430  if (strlen(distinguishedName) == 0)
7431    {
7432      rc = container_create(ldap_handle, dn_path, afterc, after);
7433      return(rc);
7434    }
7435 
7436  container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
7437  rc = container_adupdate(ldap_handle, dn_path, "", distinguishedName, afterc,
7438                          after);
7439
7440  return(rc);
7441}
7442
7443int container_get_distinguishedName(LDAP *ldap_handle, char *dn_path,
7444                                    char *distinguishedName, int count,
7445                                    char **av)
7446{
7447  char      *attr_array[3];
7448  LK_ENTRY  *group_base;
7449  int       group_count;
7450  char      dName[256];
7451  char      cName[256];
7452  char      filter[512];
7453  int       rc;
7454
7455  memset(filter, '\0', sizeof(filter));
7456  memset(dName, '\0', sizeof(dName));
7457  memset(cName, '\0', sizeof(cName));
7458  container_get_dn(av[CONTAINER_NAME], dName);
7459  container_get_name(av[CONTAINER_NAME], cName);
7460
7461  if (strlen(dName) == 0)
7462    {
7463      com_err(whoami, 0, "Unable to process invalid LDAP container name %s",
7464              av[CONTAINER_NAME]);
7465      return(AD_INVALID_NAME);
7466    }
7467
7468  if (!check_container_name(cName))
7469    {
7470      com_err(whoami, 0, "Unable to process invalid LDAP container name %s",
7471              cName);
7472      return(AD_INVALID_NAME);
7473    }
7474 
7475  sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))",
7476          av[CONTAINER_ROWID]);
7477  attr_array[0] = "distinguishedName";
7478  attr_array[1] = NULL;
7479  group_count = 0;
7480  group_base = NULL;
7481
7482  if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
7483                           &group_base, &group_count,
7484                           LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7485    {
7486      if (group_count == 1)
7487        {
7488          strcpy(distinguishedName, group_base->value);
7489        }
7490
7491      linklist_free(group_base);
7492      group_base = NULL;
7493      group_count = 0;
7494    }
7495
7496  if (strlen(distinguishedName) == 0)
7497    {
7498      sprintf(filter, "(&(objectClass=organizationalUnit)"
7499              "(distinguishedName=%s,%s))", dName, dn_path);
7500      attr_array[0] = "distinguishedName";
7501      attr_array[1] = NULL;
7502      group_count = 0;
7503      group_base = NULL;
7504
7505      if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
7506                               &group_base, &group_count,
7507                               LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7508        {
7509          if (group_count == 1)
7510            {
7511              strcpy(distinguishedName, group_base->value);
7512            }
7513
7514          linklist_free(group_base);
7515          group_base = NULL;
7516          group_count = 0;
7517        }
7518    }
7519
7520  return(0);
7521}
7522
7523int container_adupdate(LDAP *ldap_handle, char *dn_path, char *dName,
7524                       char *distinguishedName, int count, char **av)
7525{
7526  char      *attr_array[5];
7527  LK_ENTRY  *group_base;
7528  LK_ENTRY  *pPtr;
7529  LDAPMod   *mods[20];
7530  int       group_count;
7531  char      filter[512];
7532  char      *moiraId_v[] = {NULL, NULL};
7533  char      *desc_v[] = {NULL, NULL};
7534  char      *managedBy_v[] = {NULL, NULL};
7535  char      managedByDN[256];
7536  char      moiraId[64];
7537  char      desc[256];
7538  char      ad_path[512];
7539  int       rc;
7540  int       i;
7541  int       n;
7542
7543
7544  strcpy(ad_path, distinguishedName);
7545
7546  if (strlen(dName) != 0)
7547    sprintf(ad_path, "%s,%s", dName, dn_path);
7548
7549  sprintf(filter, "(&(objectClass=organizationalUnit)(distinguishedName=%s))",
7550          ad_path);
7551
7552  if (strlen(av[CONTAINER_ID]) != 0)
7553    sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))",
7554            av[CONTAINER_ROWID]);
7555
7556  attr_array[0] = "mitMoiraId";
7557  attr_array[1] = "description";
7558  attr_array[2] = "managedBy";
7559  attr_array[3] = NULL;
7560  group_count = 0;
7561  group_base = NULL;
7562
7563  if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
7564                           &group_base, &group_count,
7565                           LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
7566    {
7567      com_err(whoami, 0, "Unable to retreive container info for %s : %s",
7568              av[CONTAINER_NAME], ldap_err2string(rc));
7569      return(rc);
7570    }
7571
7572  memset(managedByDN, '\0', sizeof(managedByDN));
7573  memset(moiraId, '\0', sizeof(moiraId));
7574  memset(desc, '\0', sizeof(desc));
7575  pPtr = group_base;
7576
7577  while (pPtr)
7578    {
7579      if (!strcasecmp(pPtr->attribute, "description"))
7580        strcpy(desc, pPtr->value);
7581      else if (!strcasecmp(pPtr->attribute, "managedBy"))
7582        strcpy(managedByDN, pPtr->value);
7583      else if (!strcasecmp(pPtr->attribute, "mitMoiraId"))
7584        strcpy(moiraId, pPtr->value);
7585      pPtr = pPtr->next;
7586    }
7587
7588  linklist_free(group_base);
7589  group_base = NULL;
7590  group_count = 0;
7591
7592  n = 0;
7593  if (strlen(av[CONTAINER_ROWID]) != 0)
7594    {
7595      moiraId_v[0] = av[CONTAINER_ROWID];
7596      ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_REPLACE);
7597    }
7598
7599  if (strlen(av[CONTAINER_DESC]) != 0)
7600    {
7601      attribute_update(ldap_handle, ad_path, av[CONTAINER_DESC], "description",
7602                       dName);
7603    }
7604  else
7605    {
7606      if (strlen(desc) != 0)
7607        {
7608          attribute_update(ldap_handle, ad_path, "", "description", dName);
7609        }
7610    }
7611
7612  if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
7613    {
7614      if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
7615        {
7616          if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID],
7617                              kerberos_ou))
7618            {
7619              sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID],
7620                      kerberos_ou, dn_path);
7621              managedBy_v[0] = managedByDN;
7622              ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
7623            }
7624          else
7625            {
7626              if (strlen(managedByDN) != 0)
7627                {
7628                  attribute_update(ldap_handle, ad_path, "", "managedBy",
7629                                   dName);
7630                }
7631            }
7632        }
7633      else
7634        {
7635          memset(filter, '\0', sizeof(filter));
7636
7637          if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
7638            {
7639              sprintf(filter, "(&(cn=%s)(&(objectCategory=person)"
7640                      "(objectClass=user)))", av[CONTAINER_ID]);
7641            }
7642
7643          if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
7644            {
7645              sprintf(filter, "(&(objectClass=group)(cn=%s))",
7646                      av[CONTAINER_ID]);
7647            }
7648
7649          if (strlen(filter) != 0)
7650            {
7651              attr_array[0] = "distinguishedName";
7652              attr_array[1] = NULL;
7653              group_count = 0;
7654              group_base = NULL;
7655              if ((rc = linklist_build(ldap_handle, dn_path, filter,
7656                                       attr_array, &group_base, &group_count,
7657                                       LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7658                {
7659                  if (group_count == 1)
7660                    {
7661                      strcpy(managedByDN, group_base->value);
7662                      managedBy_v[0] = managedByDN;
7663                      ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
7664                    }
7665                  else
7666                    {
7667                      if (strlen(managedByDN) != 0)
7668                        {
7669                          attribute_update(ldap_handle, ad_path, "",
7670                                           "managedBy", dName);
7671                        }
7672                    }
7673
7674                  linklist_free(group_base);
7675                  group_base = NULL;
7676                  group_count = 0;
7677                }
7678            }
7679          else
7680            {
7681              if (strlen(managedByDN) != 0)
7682                {
7683                  attribute_update(ldap_handle, ad_path, "", "managedBy",
7684                                   dName);
7685                }
7686            }
7687        }
7688    }
7689
7690  mods[n] = NULL;
7691
7692  if (n == 0)
7693    return(LDAP_SUCCESS);
7694
7695  rc = ldap_modify_s(ldap_handle, ad_path, mods);
7696
7697  for (i = 0; i < n; i++)
7698    free(mods[i]);
7699
7700  if (rc != LDAP_SUCCESS)
7701    {
7702      com_err(whoami, 0, "Unable to modify container info for %s : %s",
7703              av[CONTAINER_NAME], ldap_err2string(rc));
7704      return(rc);
7705    }
7706 
7707  return(rc);
7708}
7709
7710int container_move_objects(LDAP *ldap_handle, char *dn_path, char *dName)
7711{
7712  char      *attr_array[3];
7713  LK_ENTRY  *group_base;
7714  LK_ENTRY  *pPtr;
7715  int       group_count;
7716  char      filter[512];
7717  char      new_cn[128];
7718  char      temp[256];
7719  int       rc;
7720  int       NumberOfEntries = 10;
7721  int       i;
7722  int       count;
7723
7724  rc = ldap_set_option(ldap_handle, LDAP_OPT_SIZELIMIT, &NumberOfEntries);
7725
7726  for (i = 0; i < 3; i++)
7727    {
7728      memset(filter, '\0', sizeof(filter));
7729
7730      if (i == 0)
7731        {
7732          strcpy(filter, "(!(|(objectClass=computer)"
7733                 "(objectClass=organizationalUnit)))");
7734          attr_array[0] = "cn";
7735          attr_array[1] = NULL;
7736        }
7737      else if (i == 1)
7738        {
7739          strcpy(filter, "(objectClass=computer)");
7740          attr_array[0] = "cn";
7741          attr_array[1] = NULL;
7742        }
7743      else
7744        {
7745          strcpy(filter, "(objectClass=organizationalUnit)");
7746          attr_array[0] = "ou";
7747          attr_array[1] = NULL;
7748        }
7749
7750      while (1)
7751        {
7752          if ((rc = linklist_build(ldap_handle, dName, filter, attr_array,
7753                                   &group_base, &group_count,
7754                                   LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
7755            {
7756              break;
7757            }
7758
7759          if (group_count == 0)
7760            break;
7761
7762          pPtr = group_base;
7763
7764          while(pPtr)
7765            {
7766              if (!strcasecmp(pPtr->attribute, "cn"))
7767                {
7768                  sprintf(new_cn, "cn=%s", pPtr->value);
7769                  if (i == 0)
7770                    sprintf(temp, "%s,%s", orphans_other_ou, dn_path);
7771                  if (i == 1)
7772                    sprintf(temp, "%s,%s", orphans_machines_ou, dn_path);
7773                  count = 1;
7774
7775                  while (1)
7776                    {
7777                      rc = ldap_rename_s(ldap_handle, pPtr->dn, new_cn, temp,
7778                                         TRUE, NULL, NULL);
7779                      if (rc == LDAP_ALREADY_EXISTS)
7780                        {
7781                          sprintf(new_cn, "cn=%s_%d", pPtr->value, count);
7782                          ++count;
7783                        }
7784                      else
7785                        break;
7786                    }
7787                }
7788              else if (!strcasecmp(pPtr->attribute, "ou"))
7789                {
7790                  rc = ldap_delete_s(ldap_handle, pPtr->dn);
7791                }
7792
7793              pPtr = pPtr->next;
7794            }
7795
7796          linklist_free(group_base);
7797          group_base = NULL;
7798          group_count = 0;
7799        }
7800    }
7801
7802  return(0);
7803}
7804
7805int get_machine_ou(LDAP *ldap_handle, char *dn_path, char *member,
7806                   char *machine_ou, char *NewMachineName)
7807{
7808  LK_ENTRY  *group_base;
7809  int  group_count;
7810  int  i;
7811  char filter[128];
7812  char *attr_array[3];
7813  char cn[256];
7814  char dn[256];
7815  char temp[256];
7816  char *pPtr;
7817  int   rc;
7818
7819  strcpy(NewMachineName, member);
7820  rc = moira_connect();
7821  rc = GetMachineName(NewMachineName);
7822  moira_disconnect();
7823
7824  if (strlen(NewMachineName) == 0)
7825    {
7826      com_err(whoami, 0, "Unable to find alais for machine %s in Moira",
7827              member);
7828      return(1);
7829    }
7830
7831  pPtr = NULL;
7832  pPtr = strchr(NewMachineName, '.');
7833
7834  if (pPtr != NULL)
7835    (*pPtr) = '\0';
7836
7837  group_base = NULL;
7838  group_count = 0;
7839  sprintf(filter, "(sAMAccountName=%s$)", NewMachineName);
7840  attr_array[0] = "cn";
7841  attr_array[1] = NULL;
7842  sprintf(temp, "%s", dn_path);
7843
7844  if ((rc = linklist_build(ldap_handle, temp, filter, attr_array,
7845                           &group_base, &group_count,
7846                           LDAP_SCOPE_SUBTREE)) != 0)
7847    {
7848      com_err(whoami, 0, "Unable to process machine %s : %s",
7849              member, ldap_err2string(rc));
7850      return(1);
7851    }
7852
7853  if (group_count != 1)
7854    {
7855      return(1);
7856    }
7857
7858  strcpy(dn, group_base->dn);
7859  strcpy(cn, group_base->value);
7860
7861  for (i = 0; i < (int)strlen(dn); i++)
7862    dn[i] = tolower(dn[i]);
7863
7864  for (i = 0; i < (int)strlen(cn); i++)
7865    cn[i] = tolower(cn[i]);
7866
7867  linklist_free(group_base);
7868  pPtr = NULL;
7869  pPtr = strstr(dn, cn);
7870
7871  if (pPtr == NULL)
7872    {
7873      com_err(whoami, 0, "Unable to process machine %s",
7874              member);
7875      return(1);
7876    }
7877
7878  pPtr += strlen(cn) + 1;
7879  strcpy(machine_ou, pPtr);
7880  pPtr = NULL;
7881  pPtr = strstr(machine_ou, "dc=");
7882
7883  if (pPtr == NULL)
7884    {
7885      com_err(whoami, 0, "Unable to process machine %s",
7886              member);
7887      return(1);
7888    }
7889
7890  --pPtr;
7891  (*pPtr) = '\0';
7892
7893  return(0);
7894}
7895
7896int machine_move_to_ou(LDAP *ldap_handle, char * dn_path,
7897                       char *MoiraMachineName, char *DestinationOu)
7898{
7899  char        NewCn[128];
7900  char        OldDn[512];
7901  char        MachineName[128];
7902  char        filter[128];
7903  char        *attr_array[3];
7904  char        NewOu[256];
7905  char        *cPtr = NULL;
7906  int         group_count;
7907  long        rc;
7908  LK_ENTRY    *group_base;
7909
7910  group_count = 0;
7911  group_base = NULL;
7912 
7913  strcpy(MachineName, MoiraMachineName);
7914  rc = GetMachineName(MachineName);
7915
7916  if (strlen(MachineName) == 0)
7917    {
7918      com_err(whoami, 0, "Unable to find alais for machine %s in Moira",
7919              MoiraMachineName);
7920      return(1);
7921    }
7922 
7923  cPtr = strchr(MachineName, '.');
7924
7925  if (cPtr != NULL)
7926    (*cPtr) = '\0';
7927
7928  sprintf(filter, "(sAMAccountName=%s$)", MachineName);
7929  attr_array[0] = "sAMAccountName";
7930  attr_array[1] = NULL;
7931
7932  if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
7933                           &group_base,
7934                           &group_count, LDAP_SCOPE_SUBTREE)) != 0)
7935    {
7936      com_err(whoami, 0, "Unable to process machine %s : %s",
7937              MoiraMachineName, ldap_err2string(rc));
7938      return(1);
7939    }
7940 
7941  if (group_count == 1)
7942    strcpy(OldDn, group_base->dn);
7943
7944  linklist_free(group_base);
7945  group_base = NULL;
7946
7947  if (group_count != 1)
7948    {
7949      com_err(whoami, 0, "Unable to find machine %s in directory: %s",
7950              MoiraMachineName);
7951      return(1);
7952    }
7953
7954  sprintf(NewOu, "%s,%s", DestinationOu, dn_path);
7955  cPtr = strchr(OldDn, ',');
7956
7957  if (cPtr != NULL)
7958    {
7959      ++cPtr;
7960      if (!strcasecmp(cPtr, NewOu))
7961        return(0);
7962    }
7963
7964  sprintf(NewCn, "CN=%s", MachineName);
7965  rc = ldap_rename_s(ldap_handle, OldDn, NewCn, NewOu, TRUE, NULL, NULL);
7966
7967  return(rc);
7968}
7969
7970int machine_check(LDAP *ldap_handle, char *dn_path, char *machine_name)
7971{
7972  char    Name[128];
7973  char    *pPtr;
7974  int     rc;
7975 
7976  memset(Name, '\0', sizeof(Name));
7977  strcpy(Name, machine_name);
7978  pPtr = NULL;
7979  pPtr = strchr(Name, '.');
7980
7981  if (pPtr != NULL)
7982    (*pPtr) = '\0';
7983
7984  strcat(Name, "$");
7985  return(!(rc = checkADname(ldap_handle, dn_path, Name)));
7986}
7987
7988int machine_get_moira_container(LDAP *ldap_handle, char *dn_path,
7989                                char *machine_name, char *container_name)
7990{
7991  int     rc;
7992  char    *av[2];
7993  char    *call_args[2];
7994 
7995  av[0] = machine_name;
7996  call_args[0] = (char *)container_name;
7997  rc = mr_query("get_machine_to_container_map", 1, av,
7998                machine_GetMoiraContainer, call_args);
7999  return(rc);
8000}
8001
8002int machine_GetMoiraContainer(int ac, char **av, void *ptr)
8003{
8004  char **call_args;
8005 
8006  call_args = ptr;
8007  strcpy(call_args[0], av[1]);
8008  return(0);
8009}
8010
8011int Moira_container_group_create(char **after)
8012{
8013  long rc;
8014  char GroupName[64];
8015  char *argv[20];
8016 
8017  memset(GroupName, '\0', sizeof(GroupName));
8018  rc = Moira_groupname_create(GroupName, after[CONTAINER_NAME],
8019                              after[CONTAINER_ROWID]);
8020  if (rc)
8021    return rc;
8022 
8023  argv[L_NAME] = GroupName;
8024  argv[L_ACTIVE] = "1";
8025  argv[L_PUBLIC] = "0";
8026  argv[L_HIDDEN] = "0";
8027  argv[L_MAILLIST] = "0";
8028  argv[L_GROUP] = "1";
8029  argv[L_GID] = UNIQUE_GID;
8030  argv[L_NFSGROUP] = "0";
8031  argv[L_MAILMAN] = "0";
8032  argv[L_MAILMAN_SERVER] = "[NONE]";
8033  argv[L_DESC] = "auto created container group";
8034  argv[L_ACE_TYPE] = "USER";
8035  argv[L_MEMACE_TYPE] = "USER";
8036  argv[L_ACE_NAME] = "sms";
8037  argv[L_MEMACE_NAME] = "sms";
8038
8039  if (rc = mr_query("add_list", 15, argv, NULL, NULL))
8040    {
8041      com_err(whoami, 0,
8042              "Unable to create container group %s for container %s: %s",
8043              GroupName, after[CONTAINER_NAME], error_message(rc));
8044    }
8045
8046  Moira_setContainerGroup(after[CONTAINER_NAME], GroupName);
8047  Moira_addGroupToParent(after[CONTAINER_NAME], GroupName);
8048 
8049  return(rc);
8050}
8051
8052int Moira_container_group_update(char **before, char **after)
8053{
8054  long rc;
8055  char BeforeGroupName[64];
8056  char AfterGroupName[64];
8057  char *argv[20];
8058 
8059  if (!strcasecmp(after[CONTAINER_NAME], before[CONTAINER_NAME]))
8060    return(0);
8061
8062  memset(BeforeGroupName, '\0', sizeof(BeforeGroupName));
8063  Moira_getGroupName(after[CONTAINER_NAME], BeforeGroupName, 0);
8064  if (strlen(BeforeGroupName) == 0)
8065    return(0);
8066
8067  memset(AfterGroupName, '\0', sizeof(AfterGroupName));
8068  rc = Moira_groupname_create(AfterGroupName, after[CONTAINER_NAME],
8069                              after[CONTAINER_ROWID]);
8070  if (rc)
8071    return rc;
8072
8073  if (strcasecmp(BeforeGroupName, AfterGroupName))
8074    {
8075      argv[L_NAME] = BeforeGroupName;
8076      argv[L_NAME + 1] = AfterGroupName;
8077      argv[L_ACTIVE + 1] = "1";
8078      argv[L_PUBLIC + 1] = "0";
8079      argv[L_HIDDEN + 1] = "0";
8080      argv[L_MAILLIST + 1] = "0";
8081      argv[L_GROUP + 1] = "1";
8082      argv[L_GID + 1] = UNIQUE_GID;
8083      argv[L_NFSGROUP + 1] = "0";
8084      argv[L_MAILMAN + 1] = "0";
8085      argv[L_MAILMAN_SERVER + 1] = "[NONE]";
8086      argv[L_DESC + 1] = "auto created container group";
8087      argv[L_ACE_TYPE + 1] = "USER";
8088      argv[L_MEMACE_TYPE + 1] = "USER";
8089      argv[L_ACE_NAME + 1] = "sms";
8090      argv[L_MEMACE_NAME + 1] = "sms";
8091     
8092      if (rc = mr_query("update_list", 16, argv, NULL, NULL))
8093        {
8094          com_err(whoami, 0,
8095                  "Unable to rename container group from %s to %s: %s",
8096                  BeforeGroupName, AfterGroupName, error_message(rc));
8097        }
8098    }
8099 
8100  return(rc);
8101}
8102
8103int Moira_container_group_delete(char **before)
8104{
8105  long rc = 0;
8106  char *argv[13];
8107  char GroupName[64];
8108  char ParentGroupName[64];
8109 
8110  memset(ParentGroupName, '\0', sizeof(ParentGroupName));
8111  Moira_getGroupName(before[CONTAINER_NAME], ParentGroupName, 1);
8112
8113  memset(GroupName, '\0', sizeof(GroupName));
8114
8115  if (strcmp(before[CONTAINER_GROUP_NAME], "[none]"))
8116    strcpy(GroupName, before[CONTAINER_GROUP_NAME]);
8117 
8118  if ((strlen(ParentGroupName) != 0) && (strlen(GroupName) != 0))
8119    {
8120      argv[0] = ParentGroupName;
8121      argv[1] = "LIST";
8122      argv[2] = GroupName;
8123
8124      if (rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL))
8125        {
8126          com_err(whoami, 0,
8127                  "Unable to delete container group %s from list: %s",
8128                  GroupName, ParentGroupName, error_message(rc));
8129        }
8130    }
8131 
8132  if (strlen(GroupName) != 0)
8133    {
8134      argv[0] = GroupName;
8135
8136      if (rc = mr_query("delete_list", 1, argv, NULL, NULL))
8137        {
8138          com_err(whoami, 0, "Unable to delete container group %s : %s",
8139                  GroupName, error_message(rc));
8140        }
8141    }
8142 
8143  return(rc);
8144}
8145
8146int Moira_groupname_create(char *GroupName, char *ContainerName,
8147                           char *ContainerRowID)
8148{
8149  char *ptr;
8150  char *ptr1;
8151  char temp[64];
8152  char newGroupName[64];
8153  char tempGroupName[64];
8154  char tempgname[64];
8155  char *argv[1];
8156  int  i;
8157  long rc;
8158
8159  strcpy(temp, ContainerName);
8160 
8161  ptr1 = strrchr(temp, '/');
8162
8163  if (ptr1 != NULL)
8164  {
8165    *ptr1 = '\0';
8166    ptr = ++ptr1;
8167    ptr1 = strrchr(temp, '/');
8168
8169    if (ptr1 != NULL)
8170    {
8171        sprintf(tempgname, "%s-%s", ++ptr1, ptr);
8172    }
8173    else
8174        strcpy(tempgname, ptr);
8175  }
8176  else
8177    strcpy(tempgname, temp);
8178
8179  if (strlen(tempgname) > 25)
8180    tempgname[25] ='\0';
8181
8182  sprintf(newGroupName, "cnt-%s", tempgname);
8183
8184  /* change everything to lower case */
8185  ptr = newGroupName;
8186
8187  while (*ptr)
8188    {
8189      if (isupper(*ptr))
8190        *ptr = tolower(*ptr);
8191
8192      if (*ptr == ' ')
8193        *ptr = '-';
8194
8195      ptr++;
8196    }
8197
8198  strcpy(tempGroupName, newGroupName);
8199  i = (int)'0';
8200
8201  /* append 0-9 then a-z if a duplicate is found */
8202  while(1)
8203    {
8204      argv[0] = newGroupName;
8205
8206      if (rc = mr_query("get_list_info", 1, argv, NULL, NULL))
8207        {
8208          if (rc == MR_NO_MATCH)
8209            break;
8210          com_err(whoami, 0, "Moira error while creating group name for "
8211                  "container %s : %s", ContainerName, error_message(rc));
8212          return rc;
8213        }
8214
8215      sprintf(newGroupName, "%s-%c", tempGroupName, i);
8216
8217      if (i == (int)'z')
8218        {
8219          com_err(whoami, 0, "Unable to find a unique group name for "
8220                  "container %s: too many duplicate container names",
8221                  ContainerName);
8222          return 1;
8223        }
8224
8225      if (i == '9')
8226        i = 'a';
8227      else
8228        i++;
8229    }
8230
8231  strcpy(GroupName, newGroupName);
8232  return(0);
8233}
8234
8235int Moira_setContainerGroup(char *origContainerName, char *GroupName)
8236{
8237  long rc;
8238  char *argv[3];
8239 
8240  argv[0] = origContainerName;
8241  argv[1] = GroupName;
8242 
8243  if ((rc = mr_query("set_container_list", 2, argv, NULL, NULL)))
8244    {
8245      com_err(whoami, 0,
8246              "Unable to set container group %s in container %s: %s",
8247              GroupName, origContainerName, error_message(rc));
8248    }
8249 
8250  return(0);
8251}
8252
8253int Moira_addGroupToParent(char *origContainerName, char *GroupName)
8254 {
8255   char ContainerName[64];
8256   char ParentGroupName[64];
8257   char *argv[3];
8258   long rc;
8259
8260   strcpy(ContainerName, origContainerName);
8261   
8262   Moira_getGroupName(ContainerName, ParentGroupName, 1);
8263
8264   /* top-level container */
8265   if (strlen(ParentGroupName) == 0)
8266     return(0);
8267   
8268   argv[0] = ParentGroupName;
8269   argv[1] = "LIST";
8270   argv[2] = GroupName;
8271
8272   if ((rc = mr_query("add_member_to_list", 3, argv, NULL, NULL)))
8273     {
8274       com_err(whoami, 0,
8275               "Unable to add container group %s to parent group %s: %s",
8276               GroupName, ParentGroupName, error_message(rc));
8277     }
8278   
8279   return(0);
8280 }
8281
8282int Moira_getContainerGroup(int ac, char **av, void *ptr)
8283{
8284  char **call_args;
8285 
8286  call_args = ptr;
8287  strcpy(call_args[0], av[1]);
8288
8289  return(0);
8290}
8291
8292int Moira_getGroupName(char *origContainerName, char *GroupName,
8293                       int ParentFlag)
8294{
8295  char ContainerName[64];
8296  char *argv[3];
8297  char *call_args[3];
8298  char *ptr;
8299  long rc;
8300
8301  strcpy(ContainerName, origContainerName);
8302
8303  if (ParentFlag)
8304    {
8305      ptr = strrchr(ContainerName, '/');
8306
8307      if (ptr != NULL)
8308        (*ptr) = '\0';
8309      else
8310        return(0);
8311    }
8312
8313  argv[0] = ContainerName;
8314  argv[1] = NULL;
8315  call_args[0] = GroupName;
8316  call_args[1] = NULL;
8317
8318  if (!(rc = mr_query("get_container_list", 1, argv, Moira_getContainerGroup,
8319                      call_args)))
8320    {
8321      if (strlen(GroupName) != 0)
8322        return(0);
8323    }
8324
8325  if (rc)
8326    com_err(whoami, 0, "Unable to get container group from container %s: %s",
8327            ContainerName, error_message(rc));
8328  else
8329    com_err(whoami, 0, "Unable to get container group from container %s",
8330            ContainerName);
8331 
8332  return(0);
8333}
8334
8335int Moira_process_machine_container_group(char *MachineName, char* GroupName,
8336                                          int DeleteMachine)
8337{
8338  char *argv[3];
8339  long rc;
8340 
8341  if (strcmp(GroupName, "[none]") == 0)
8342    return 0;
8343
8344  argv[0] = GroupName;
8345  argv[1] = "MACHINE";
8346  argv[2] = MachineName;
8347
8348  if (!DeleteMachine)
8349    rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
8350  else
8351    rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
8352
8353  if (rc)
8354    {
8355      com_err(whoami, 0, "Unable to add machine %s to container group%s: %s",
8356              MachineName, GroupName, error_message(rc));
8357    }
8358
8359  return(0);
8360}
8361
8362int GetMachineName(char *MachineName)
8363{
8364  char    *args[2];
8365  char    NewMachineName[1024];
8366  char    *szDot;
8367  int     rc = 0;
8368  int     i;
8369  DWORD   dwLen = 0;
8370  char    *call_args[2];
8371 
8372  // If the address happens to be in the top-level MIT domain, great!
8373  strcpy(NewMachineName, MachineName);
8374
8375  for (i = 0; i < (int)strlen(NewMachineName); i++)
8376    NewMachineName[i] = toupper(NewMachineName[i]);
8377
8378  szDot = strchr(NewMachineName,'.');
8379
8380  if ((szDot) && (!strcasecmp(szDot+1, DOMAIN_SUFFIX)))
8381    {
8382      return(0);
8383    }
8384 
8385  // If not, see if it has a Moira alias in the top-level MIT domain.
8386  memset(NewMachineName, '\0', sizeof(NewMachineName));
8387  args[0] = "*";
8388  args[1] = MachineName;
8389  call_args[0] = NewMachineName;
8390  call_args[1] = NULL;
8391
8392  if (rc = mr_query("get_hostalias", 2, args, ProcessMachineName, call_args))
8393    {
8394      com_err(whoami, 0, "Unable to resolve machine name %s : %s",
8395              MachineName, error_message(rc));
8396      strcpy(MachineName, "");
8397      return(0);
8398    }
8399 
8400  if (strlen(NewMachineName) != 0)
8401    strcpy(MachineName, NewMachineName);
8402  else
8403    strcpy(MachineName, "");
8404
8405  return(0);
8406}
8407
8408int ProcessMachineName(int ac, char **av, void *ptr)
8409{
8410  char    **call_args;
8411  char    MachineName[1024];
8412  char    *szDot;
8413  int     i;
8414 
8415  call_args = ptr;
8416
8417  if (strlen(call_args[0]) == 0)
8418    {
8419      strcpy(MachineName, av[0]);
8420
8421      for (i = 0; i < (int)strlen(MachineName); i++)
8422        MachineName[i] = toupper(MachineName[i]);
8423
8424      szDot = strchr(MachineName,'.');
8425
8426        if ((szDot) && (!strcasecmp(szDot+1,DOMAIN_SUFFIX)))
8427          {
8428            strcpy(call_args[0], MachineName);
8429          }
8430    }
8431
8432  return(0);
8433}
8434
8435void SwitchSFU(LDAPMod **mods, int *UseSFU30, int n)
8436{
8437  int i;
8438 
8439  if (*UseSFU30)
8440    {
8441      for (i = 0; i < n; i++)
8442        {
8443          if (!strcmp(mods[i]->mod_type, "msSFU30UidNumber"))
8444            mods[i]->mod_type = "uidNumber";
8445        }
8446
8447      (*UseSFU30) = 0;
8448    }
8449  else
8450    {
8451      for (i = 0; i < n; i++)
8452        {
8453          if (!strcmp(mods[i]->mod_type, "uidNumber"))
8454            mods[i]->mod_type = "msSFU30UidNumber";
8455        }
8456
8457      (*UseSFU30) = 1;
8458    }
8459}
8460
8461int SetHomeDirectory(LDAP *ldap_handle, char *user_name,
8462                     char *DistinguishedName,
8463                     char *WinHomeDir, char *WinProfileDir,
8464                     char **homedir_v, char **winProfile_v,
8465                     char **drives_v, char **apple_homedir_v, LDAPMod **mods,
8466                     int OpType, int n)
8467{
8468  char cWeight[3];
8469  char cPath[1024];
8470  char path[1024];
8471  char winPath[1024];
8472  char winProfile[1024];
8473  char homeDrive[8];
8474  char homedir[1024];
8475  char apple_homedir[1024];
8476  int  last_weight;
8477  int  i;
8478  int  rc;
8479  LDAPMod *DelMods[20];
8480  char *argv[3];
8481  char *save_argv[FS_END];
8482  char *fsgroup_save_argv[2];
8483
8484  memset(homeDrive, '\0', sizeof(homeDrive));
8485  memset(path, '\0', sizeof(path));
8486  memset(winPath, '\0', sizeof(winPath));
8487  memset(winProfile, '\0', sizeof(winProfile));
8488
8489  if(!ActiveDirectory)
8490    {
8491      if (rc = moira_connect())
8492        {
8493          critical_alert(whoami, "Ldap incremental",
8494                         "Error contacting Moira server : %s",
8495                         error_message(rc));
8496          return(n);
8497        }
8498     
8499      argv[0] = user_name;
8500
8501      if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info,
8502                          save_argv)))
8503        {
8504          if(!strcmp(save_argv[FS_TYPE], "FSGROUP") ||
8505             !strcmp(save_argv[FS_TYPE], "MUL"))
8506            {
8507       
8508              argv[0] = save_argv[FS_NAME];
8509              fsgCount = 0;
8510             
8511              if (!(rc = mr_query("get_fsgroup_members", 1, argv,
8512                                  save_fsgroup_info, fsgroup_save_argv)))
8513                {
8514                  if(fsgCount)
8515                    {
8516                      argv[0] = fsgroup_save_argv[0];
8517                     
8518                      if (!(rc = mr_query("get_filesys_by_label", 1, argv,
8519                                          save_query_info, save_argv)))
8520                        {
8521                          strcpy(path, save_argv[FS_PACK]);
8522                        }
8523                    }
8524                }
8525            }
8526          else
8527            {
8528              strcpy(path, save_argv[FS_PACK]);
8529            }
8530        }
8531     
8532      moira_disconnect();
8533
8534      if (strlen(path))
8535        {
8536          if (!strnicmp(path, AFS, strlen(AFS)))
8537            {
8538              sprintf(homedir, "%s", path);
8539              sprintf(apple_homedir, "%s/MacData", path);
8540              homedir_v[0] = homedir;
8541              apple_homedir_v[0] = apple_homedir;
8542              ADD_ATTR("homeDirectory", homedir_v, OpType);
8543              ADD_ATTR("apple-user-homeDirectory", apple_homedir_v,
8544                       OpType);
8545            }
8546        }
8547      else
8548        {
8549          homedir_v[0] = "NONE";
8550          apple_homedir_v[0] = "NONE";
8551          ADD_ATTR("homeDirectory", homedir_v, OpType);
8552          ADD_ATTR("apple-user-homeDirectory", apple_homedir_v,
8553                   OpType);
8554        }
8555
8556      return(n);
8557    }
8558 
8559  if ((!strcasecmp(WinHomeDir, "[afs]")) ||
8560      (!strcasecmp(WinProfileDir, "[afs]")))
8561    {
8562      if (rc = moira_connect())
8563        {
8564          critical_alert(whoami, "Ldap incremental",
8565                         "Error contacting Moira server : %s",
8566                         error_message(rc));
8567          return(n);
8568        }
8569     
8570      argv[0] = user_name;
8571
8572      if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info,
8573                          save_argv)))
8574        {
8575          if(!strcmp(save_argv[FS_TYPE], "FSGROUP") ||
8576             !strcmp(save_argv[FS_TYPE], "MUL"))
8577            {
8578       
8579              argv[0] = save_argv[FS_NAME];
8580              fsgCount = 0;
8581             
8582              if (!(rc = mr_query("get_fsgroup_members", 1, argv,
8583                                  save_fsgroup_info, fsgroup_save_argv)))
8584                {
8585                  if(fsgCount)
8586                    {
8587                      argv[0] = fsgroup_save_argv[0];
8588                     
8589                      if (!(rc = mr_query("get_filesys_by_label", 1, argv,
8590                                          save_query_info, save_argv)))
8591                        {
8592                          strcpy(path, save_argv[FS_PACK]);
8593                        }
8594                    }
8595                }
8596            }
8597          else
8598            {
8599              strcpy(path, save_argv[FS_PACK]);
8600            }
8601        }
8602     
8603      moira_disconnect();
8604
8605      if (strlen(path))
8606        {
8607          if (!strnicmp(path, AFS, strlen(AFS)))
8608            {
8609              AfsToWinAfs(path, winPath);
8610              strcpy(winProfile, winPath);
8611              strcat(winProfile, "\\.winprofile");
8612            }
8613        }
8614      else
8615        return(n);
8616    }
8617
8618    if ((!strcasecmp(WinHomeDir, "[dfs]")) ||
8619        (!strcasecmp(WinProfileDir, "[dfs]")))
8620    {
8621      sprintf(path, "\\\\%s\\dfs\\profiles\\%c\\%s", ldap_domain,
8622              user_name[0], user_name);
8623
8624      if (!strcasecmp(WinProfileDir, "[dfs]"))
8625        {
8626          strcpy(winProfile, path);
8627          strcat(winProfile, "\\.winprofile");
8628        }
8629
8630      if (!strcasecmp(WinHomeDir, "[dfs]"))
8631        strcpy(winPath, path);
8632    }
8633   
8634    if (!strcasecmp(WinHomeDir, "[local]"))
8635      memset(winPath, '\0', sizeof(winPath));
8636    else if (!strcasecmp(WinHomeDir, "[afs]") ||
8637             !strcasecmp(WinHomeDir, "[dfs]"))
8638      {
8639        strcpy(homeDrive, "H:");
8640      }
8641    else
8642      {
8643        strcpy(winPath, WinHomeDir);
8644        if (!strncmp(WinHomeDir, "\\\\", 2))
8645          {
8646            strcpy(homeDrive, "H:");
8647          }       
8648      }
8649   
8650    // nothing needs to be done if WinProfileDir is [afs].
8651    if (!strcasecmp(WinProfileDir, "[local]"))
8652      memset(winProfile, '\0', sizeof(winProfile));
8653    else if (strcasecmp(WinProfileDir, "[afs]") &&
8654             strcasecmp(WinProfileDir, "[dfs]"))
8655      {
8656        strcpy(winProfile, WinProfileDir);
8657      }
8658   
8659    if (strlen(winProfile) != 0)
8660      {
8661        if (winProfile[strlen(winProfile) - 1] == '\\')
8662          winProfile[strlen(winProfile) - 1] = '\0';
8663      }
8664
8665    if (strlen(winPath) != 0)
8666      {
8667        if (winPath[strlen(winPath) - 1] == '\\')
8668          winPath[strlen(winPath) - 1] = '\0';
8669      }
8670   
8671    if ((winProfile[1] == ':') && (strlen(winProfile) == 2))
8672      strcat(winProfile, "\\");
8673
8674    if ((winPath[1] == ':') && (strlen(winPath) == 2))
8675      strcat(winPath, "\\");
8676   
8677    if (strlen(winPath) == 0)
8678      {
8679        if (OpType == LDAP_MOD_REPLACE)
8680          {
8681            i = 0;
8682            DEL_ATTR("homeDirectory", LDAP_MOD_DELETE);
8683            DelMods[i] = NULL;
8684            //unset homeDirectory attribute for user.
8685            rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8686            free(DelMods[0]);
8687          }
8688      }
8689    else
8690      {
8691        homedir_v[0] = strdup(winPath);
8692        ADD_ATTR("homeDirectory", homedir_v, OpType);
8693      }
8694   
8695    if (strlen(winProfile) == 0)
8696      {
8697        if (OpType == LDAP_MOD_REPLACE)
8698          {
8699            i = 0;
8700            DEL_ATTR("profilePath", LDAP_MOD_DELETE);
8701            DelMods[i] = NULL;
8702            //unset profilePate attribute for user.
8703            rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8704            free(DelMods[0]);
8705          }
8706      }
8707    else
8708      {
8709        winProfile_v[0] = strdup(winProfile);
8710        ADD_ATTR("profilePath", winProfile_v, OpType);
8711      }
8712   
8713    if (strlen(homeDrive) == 0)
8714      {
8715        if (OpType == LDAP_MOD_REPLACE)
8716          {
8717            i = 0;
8718            DEL_ATTR("homeDrive", LDAP_MOD_DELETE);
8719            DelMods[i] = NULL;
8720            //unset homeDrive attribute for user
8721            rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8722            free(DelMods[0]);
8723          }
8724      }
8725    else
8726      {
8727        drives_v[0] = strdup(homeDrive);
8728        ADD_ATTR("homeDrive", drives_v, OpType);
8729      }
8730
8731    return(n);
8732}
8733
8734int attribute_update(LDAP *ldap_handle, char *distinguished_name,
8735                     char *attribute_value, char *attribute, char *user_name)
8736{
8737  char      *mod_v[] = {NULL, NULL};
8738  LDAPMod   *DelMods[20];
8739  LDAPMod   *mods[20];
8740  int       n;
8741  int       i;
8742  int       rc;
8743 
8744  if (strlen(attribute_value) == 0)
8745    {
8746      i = 0;
8747      DEL_ATTR(attribute, LDAP_MOD_DELETE);
8748      DelMods[i] = NULL;
8749      rc = ldap_modify_s(ldap_handle, distinguished_name, DelMods);
8750      free(DelMods[0]);
8751    }
8752  else
8753    {
8754      n = 0;
8755      mod_v[0] = attribute_value;
8756      ADD_ATTR(attribute, mod_v, LDAP_MOD_REPLACE);
8757      mods[n] = NULL;
8758
8759      if ((rc = ldap_modify_s(ldap_handle, distinguished_name,
8760                              mods)) != LDAP_SUCCESS)
8761        {
8762          free(mods[0]);
8763          n = 0;
8764          mod_v[0] = attribute_value;
8765          ADD_ATTR(attribute, mod_v, LDAP_MOD_ADD);
8766          mods[n] = NULL;
8767
8768          if ((rc = ldap_modify_s(ldap_handle, distinguished_name,
8769                                  mods)) != LDAP_SUCCESS)
8770            {
8771              com_err(whoami, 0, "Unable to change the %s attribute for %s "
8772                      "in the directory : %s",
8773                      attribute, user_name, ldap_err2string(rc));
8774            }
8775        }
8776
8777      free(mods[0]);
8778    }
8779 
8780  return(rc);
8781}
8782
8783void StringTrim(char *StringToTrim)
8784{
8785  char *t, *s;
8786  char *save;
8787
8788  save = strdup(StringToTrim);
8789
8790  s = save;
8791
8792  while (isspace(*s))
8793    s++;
8794
8795  /* skip to end of string */
8796  if (*s == '\0')
8797    {
8798      if (*save)
8799        *save = '\0';
8800      strcpy(StringToTrim, save);
8801      return;
8802    }
8803 
8804  for (t = s; *t; t++)
8805    continue;
8806
8807  while (t > s)
8808    {
8809      --t;
8810      if (!isspace(*t))
8811        {
8812          t++;
8813          break;
8814        }
8815    }
8816
8817  if (*t)
8818    *t = '\0';
8819 
8820  strcpy(StringToTrim, s);
8821  return;
8822}
8823
8824int ReadConfigFile(char *DomainName)
8825{
8826    int     Count;
8827    int     i;
8828    int     k;
8829    char    temp[256];
8830    char    temp1[256];
8831    FILE    *fptr;
8832
8833    Count = 0;
8834
8835    sprintf(temp, "%s%s.cfg", CFG_PATH, DomainName);
8836
8837    if ((fptr = fopen(temp, "r")) != NULL)
8838      {
8839        while (fgets(temp, sizeof(temp), fptr) != 0)
8840          {
8841            for (i = 0; i < (int)strlen(temp); i++)
8842              temp[i] = toupper(temp[i]);
8843
8844            if (temp[strlen(temp) - 1] == '\n')
8845              temp[strlen(temp) - 1] = '\0';
8846
8847            StringTrim(temp);
8848
8849            if (strlen(temp) == 0)
8850              continue;
8851
8852            if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
8853              {
8854                if (strlen(temp) > (strlen(DOMAIN)))
8855                  {
8856                    strcpy(ldap_domain, &temp[strlen(DOMAIN)]);
8857                    StringTrim(ldap_domain);
8858                  }
8859              }
8860            else if (!strncmp(temp, REALM, strlen(REALM)))
8861              {
8862                if (strlen(temp) > (strlen(REALM)))
8863                  {
8864                    strcpy(ldap_realm, &temp[strlen(REALM)]);
8865                    StringTrim(ldap_realm);
8866                  }
8867              }
8868            else if (!strncmp(temp, PORT, strlen(PORT)))
8869              {
8870                if (strlen(temp) > (strlen(PORT)))
8871                  {
8872                    strcpy(ldap_port, &temp[strlen(PORT)]);
8873                    StringTrim(ldap_port);
8874                  }
8875              }
8876            else if (!strncmp(temp, PRINCIPALNAME, strlen(PRINCIPALNAME)))
8877              {
8878                if (strlen(temp) > (strlen(PRINCIPALNAME)))
8879                  {
8880                    strcpy(PrincipalName, &temp[strlen(PRINCIPALNAME)]);
8881                    StringTrim(PrincipalName);
8882                  }
8883              }
8884            else if (!strncmp(temp, SERVER, strlen(SERVER)))
8885              {
8886                if (strlen(temp) > (strlen(SERVER)))
8887                  {
8888                    ServerList[Count] = calloc(1, 256);
8889                    strcpy(ServerList[Count], &temp[strlen(SERVER)]);
8890                    StringTrim(ServerList[Count]);
8891                    ++Count;
8892                  }
8893              }
8894            else if (!strncmp(temp, MSSFU, strlen(MSSFU)))
8895              {
8896                if (strlen(temp) > (strlen(MSSFU)))
8897                  {
8898                    strcpy(temp1, &temp[strlen(MSSFU)]);
8899                    StringTrim(temp1);
8900                    if (!strcmp(temp1, SFUTYPE))
8901                      UseSFU30 = 1;
8902                  }
8903              }
8904            else if (!strncmp(temp, GROUP_SUFFIX, strlen(GROUP_SUFFIX)))
8905              {
8906                if (strlen(temp) > (strlen(GROUP_SUFFIX)))
8907                  {
8908                    strcpy(temp1, &temp[strlen(GROUP_SUFFIX)]);
8909                    StringTrim(temp1);
8910                    if (!strcasecmp(temp1, "NO"))
8911                      {
8912                        UseGroupSuffix = 0;
8913                        memset(group_suffix, '\0', sizeof(group_suffix));
8914                      }
8915                  }
8916              }
8917            else if (!strncmp(temp, GROUP_TYPE, strlen(GROUP_TYPE)))
8918              {
8919                if (strlen(temp) > (strlen(GROUP_TYPE)))
8920                  {
8921                    strcpy(temp1, &temp[strlen(GROUP_TYPE)]);
8922                    StringTrim(temp1);
8923                    if (!strcasecmp(temp1, "UNIVERSAL"))
8924                      UseGroupUniversal = 1;
8925                  }
8926              }
8927            else if (!strncmp(temp, SET_GROUP_ACE, strlen(SET_GROUP_ACE)))
8928              {
8929                if (strlen(temp) > (strlen(SET_GROUP_ACE)))
8930                  {
8931                    strcpy(temp1, &temp[strlen(SET_GROUP_ACE)]);
8932                    StringTrim(temp1);
8933                    if (!strcasecmp(temp1, "NO"))
8934                      SetGroupAce = 0;
8935                  }
8936              }
8937            else if (!strncmp(temp, SET_PASSWORD, strlen(SET_PASSWORD)))
8938              {
8939                if (strlen(temp) > (strlen(SET_PASSWORD)))
8940                  {
8941                    strcpy(temp1, &temp[strlen(SET_PASSWORD)]);
8942                    StringTrim(temp1);
8943                    if (!strcasecmp(temp1, "NO"))
8944                      SetPassword = 0;
8945                  }
8946              }
8947            else if (!strncmp(temp, EXCHANGE, strlen(EXCHANGE)))
8948              {
8949                if (strlen(temp) > (strlen(EXCHANGE)))
8950                  {
8951                    strcpy(temp1, &temp[strlen(EXCHANGE)]);
8952                    StringTrim(temp1);
8953                    if (!strcasecmp(temp1, "YES"))
8954                      Exchange = 1;
8955                  }
8956              }
8957            else if (!strncmp(temp, PROCESS_MACHINE_CONTAINER,
8958                              strlen(PROCESS_MACHINE_CONTAINER)))
8959              {
8960                if (strlen(temp) > (strlen(PROCESS_MACHINE_CONTAINER)))
8961                  {
8962                    strcpy(temp1, &temp[strlen(PROCESS_MACHINE_CONTAINER)]);
8963                    StringTrim(temp1);
8964                    if (!strcasecmp(temp1, "NO"))
8965                      ProcessMachineContainer = 0;
8966                  }
8967              }
8968            else if (!strncmp(temp, ACTIVE_DIRECTORY,
8969                              strlen(ACTIVE_DIRECTORY)))
8970              {
8971                if (strlen(temp) > (strlen(ACTIVE_DIRECTORY)))
8972                  {
8973                    strcpy(temp1, &temp[strlen(ACTIVE_DIRECTORY)]);
8974                    StringTrim(temp1);
8975                    if (!strcasecmp(temp1, "NO"))
8976                      ActiveDirectory = 0;
8977                  }
8978              }
8979            else if (!strncmp(temp, GROUP_POPULATE_MEMBERS,
8980                              strlen(GROUP_POPULATE_MEMBERS)))
8981              {
8982                if (strlen(temp) > (strlen(GROUP_POPULATE_MEMBERS)))
8983                  {
8984                    strcpy(temp1, &temp[strlen(GROUP_POPULATE_MEMBERS)]);
8985                    StringTrim(temp1);
8986                    if (!strcasecmp(temp1, "DELETE"))
8987                      {
8988                        GroupPopulateDelete = 1;
8989                      }
8990                  }
8991              }
8992            else if (!strncmp(temp, MAX_MEMBERS, strlen(MAX_MEMBERS)))
8993              {
8994                if (strlen(temp) > (strlen(MAX_MEMBERS)))
8995                  {
8996                    strcpy(temp1, &temp[strlen(MAX_MEMBERS)]);
8997                    StringTrim(temp1);
8998                    max_group_members = atoi(temp1);
8999                  }
9000              }
9001            else
9002              {
9003                if (strlen(ldap_domain) != 0)
9004                  {
9005                    memset(ldap_domain, '\0', sizeof(ldap_domain));
9006                    break;
9007                  }
9008
9009                if (strlen(temp) != 0)
9010                  strcpy(ldap_domain, temp);
9011              }
9012          }
9013        fclose(fptr);
9014      }
9015   
9016    if (strlen(ldap_domain) == 0)
9017      {
9018      strcpy(ldap_domain, DomainName);
9019      }
9020
9021    if (Count == 0)
9022        return(0);
9023
9024    for (i = 0; i < Count; i++)
9025      {
9026        if (ServerList[i] != 0)
9027          {
9028            for (k = 0; k < (int)strlen(ServerList[i]); k++)
9029              ServerList[i][k] = toupper(ServerList[i][k]);
9030          }
9031      }
9032   
9033    return(0);
9034}
9035
9036int ReadDomainList()
9037{
9038  int     Count;
9039  int     i;
9040  char    temp[128];
9041  char    temp1[128];
9042  FILE    *fptr;
9043  unsigned char c[11];
9044  unsigned char stuff[256];
9045  int     rc;
9046  int     ok;
9047
9048  Count = 0;
9049  sprintf(temp, "%s%s", CFG_PATH, WINADCFG);
9050
9051  if ((fptr = fopen(temp, "r")) != NULL)
9052    {
9053      while (fgets(temp, sizeof(temp), fptr) != 0)
9054        {
9055          for (i = 0; i < (int)strlen(temp); i++)
9056            temp[i] = toupper(temp[i]);
9057
9058          if (temp[strlen(temp) - 1] == '\n')
9059            temp[strlen(temp) - 1] = '\0';
9060
9061          StringTrim(temp);
9062
9063          if (strlen(temp) == 0)
9064            continue;
9065
9066          if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
9067            {
9068              if (strlen(temp) > (strlen(DOMAIN)))
9069                {
9070                  strcpy(temp1, &temp[strlen(DOMAIN)]);
9071                  StringTrim(temp1);
9072                  strcpy(temp, temp1);
9073                }
9074            }
9075         
9076          strcpy(DomainNames[Count], temp);
9077          StringTrim(DomainNames[Count]);
9078          ++Count;
9079        }
9080
9081      fclose(fptr);
9082    }
9083
9084  if (Count == 0)
9085    {
9086      critical_alert(whoami, "incremental", "%s", "ldap.incr cannot run due to a "
9087                     "configuration error in ldap.cfg");
9088      return(1);
9089    }
9090 
9091  return(0);
9092}
9093
9094int email_isvalid(const char *address) {
9095  int        count = 0;
9096  const char *c, *domain;
9097  static char *rfc822_specials = "()<>@,;:\\\"[]";
9098
9099  if(address[strlen(address) - 1] == '.')
9100    return 0;
9101   
9102  /* first we validate the name portion (name@domain) */
9103  for (c = address;  *c;  c++) {
9104    if (*c == '\"' && (c == address || *(c - 1) == '.' || *(c - 1) ==
9105                       '\"')) {
9106      while (*++c) {
9107        if (*c == '\"')
9108          break;
9109        if (*c == '\\' && (*++c == ' '))
9110          continue;
9111        if (*c <= ' ' || *c >= 127)
9112          return 0;
9113      }
9114
9115      if (!*c++)
9116        return 0;
9117      if (*c == '@')
9118        break;
9119      if (*c != '.')
9120        return 0;
9121      continue;
9122    }
9123
9124    if (*c == '@')
9125      break;
9126    if (*c <= ' ' || *c >= 127)
9127      return 0;
9128    if (strchr(rfc822_specials, *c))
9129      return 0;
9130  }
9131
9132  if (c == address || *(c - 1) == '.')
9133    return 0;
9134
9135  /* next we validate the domain portion (name@domain) */
9136  if (!*(domain = ++c)) return 0;
9137  do {
9138    if (*c == '.') {
9139      if (c == domain || *(c - 1) == '.')
9140        return 0;
9141      count++;
9142    }
9143    if (*c <= ' ' || *c >= 127)
9144      return 0;
9145    if (strchr(rfc822_specials, *c))
9146      return 0;
9147  } while (*++c);
9148
9149  return (count >= 1);
9150}
9151
9152int find_homeMDB(LDAP *ldap_handle, char *dn_path, char **homeMDB,
9153             char **homeServerName)
9154{
9155  LK_ENTRY *group_base;
9156  LK_ENTRY *sub_group_base;
9157  LK_ENTRY *gPtr;
9158  LK_ENTRY *sub_gPtr;
9159  int      group_count;
9160  int      sub_group_count;
9161  char     filter[1024];
9162  char     sub_filter[1024];
9163  char     search_path[1024];
9164  char     range[1024];
9165  char     *attr_array[3];
9166  char     *s;
9167  int      homeMDB_count = -1;
9168  int      rc;
9169  int      i;
9170  int      mdbbl_count;
9171  int      rangeStep = 1500;
9172  int      rangeLow = 0;
9173  int      rangeHigh = rangeLow + (rangeStep - 1);
9174  int      isLast = 0;
9175
9176  /* Grumble..... microsoft not making it searchable from the root *grr* */
9177
9178  memset(filter, '\0', sizeof(filter));
9179  memset(search_path, '\0', sizeof(search_path));
9180 
9181  sprintf(filter, "(objectClass=msExchMDB)");
9182  sprintf(search_path, "CN=Configuration,%s", dn_path);
9183  attr_array[0] = "distinguishedName";
9184  attr_array[1] = NULL;
9185 
9186  group_base = NULL;
9187  group_count = 0;
9188 
9189  if ((rc = linklist_build(ldap_handle, search_path, filter, attr_array,
9190                           &group_base, &group_count,
9191                           LDAP_SCOPE_SUBTREE)) != 0)
9192    {
9193      com_err(whoami, 0, "Unable to find msExchMDB %s",
9194              ldap_err2string(rc));
9195      return(rc);
9196    }
9197 
9198  if (group_count)
9199    {
9200      gPtr = group_base;
9201     
9202      while(gPtr) {
9203        if (((s = strstr(gPtr->dn, "Public")) != (char *) NULL) ||
9204            ((s = strstr(gPtr->dn, "Recover")) != (char *) NULL) ||
9205            ((s = strstr(gPtr->dn, "Reserve")) != (char *) NULL))
9206          {
9207            gPtr = gPtr->next;
9208            continue;
9209          }
9210
9211        /*
9212         * Due to limits in active directory we need to use the LDAP
9213         * range semantics to query and return all the values in
9214         * large lists, we will stop increasing the range when
9215         * the result count is 0.
9216         */
9217
9218        i = 0; 
9219        mdbbl_count = 0;
9220
9221        for(;;)
9222          {
9223            memset(sub_filter, '\0', sizeof(sub_filter));
9224            memset(range, '\0', sizeof(range));
9225            sprintf(sub_filter, "(objectClass=msExchMDB)");
9226
9227            if(isLast)
9228              sprintf(range, "homeMDBBL;Range=%d-*", rangeLow);
9229            else
9230              sprintf(range, "homeMDBBL;Range=%d-%d", rangeLow, rangeHigh);
9231
9232            attr_array[0] = range;
9233            attr_array[1] = NULL;
9234           
9235            sub_group_base = NULL;
9236            sub_group_count = 0;
9237           
9238            if ((rc = linklist_build(ldap_handle, gPtr->dn, sub_filter,
9239                                     attr_array, &sub_group_base,
9240                                     &sub_group_count,
9241                                     LDAP_SCOPE_SUBTREE)) != 0)
9242              {
9243                com_err(whoami, 0, "Unable to find homeMDBBL %s",
9244                        ldap_err2string(rc));
9245                return(rc);
9246              }
9247
9248            if(!sub_group_count)
9249              {
9250                if(isLast)
9251                  {
9252                    isLast = 0;
9253                    rangeLow = 0;
9254                    rangeHigh = rangeLow + (rangeStep - 1);
9255                    break;
9256                  }
9257                else
9258                  isLast++;
9259              }
9260
9261            mdbbl_count += sub_group_count;
9262            rangeLow = rangeHigh + 1;
9263            rangeHigh = rangeLow + (rangeStep - 1);
9264          }
9265
9266        /* First time through, need to initialize or update the least used */
9267       
9268        com_err(whoami, 0, "Mail store %s, count %d", gPtr->dn,
9269                mdbbl_count);
9270
9271        if(mdbbl_count < homeMDB_count || homeMDB_count == -1)
9272          {
9273            homeMDB_count = mdbbl_count;
9274            *homeMDB = strdup(gPtr->dn);
9275          }
9276
9277        gPtr = gPtr->next;
9278        linklist_free(sub_group_base);
9279      }
9280    }
9281
9282  linklist_free(group_base);
9283 
9284  /*
9285   * Ok found the server least allocated need to now query to get its
9286   * msExchHomeServerName so we can set it as a user attribute
9287   */
9288 
9289  attr_array[0] = "legacyExchangeDN";
9290  attr_array[1] = NULL;
9291 
9292  group_count = 0;
9293  group_base = NULL;
9294 
9295  if ((rc = linklist_build(ldap_handle, *homeMDB, filter,
9296                           attr_array, &group_base,
9297                           &group_count,
9298                           LDAP_SCOPE_SUBTREE)) != 0)
9299    {
9300      com_err(whoami, 0, "Unable to find msExchHomeServerName %s",
9301              ldap_err2string(rc));
9302      return(rc);
9303    } 
9304 
9305  if(group_count)
9306    {
9307      *homeServerName = strdup(group_base->value);
9308      if((s = strrchr(*homeServerName, '/')) != (char *) NULL)
9309        {
9310          *s = '\0';
9311        }
9312    }
9313
9314  linklist_free(group_base);
9315 
9316  return(rc);
9317}
9318     
9319char *lowercase(char *s)
9320{
9321  char *p;
9322
9323  for (p = s; *p; p++)
9324    {
9325      if (isupper(*p))
9326        *p = tolower(*p);
9327    }
9328  return s;
9329}
9330
9331char *uppercase(char *s)
9332{
9333  char *p;
9334
9335  for (p = s; *p; p++)
9336    {
9337      if (islower(*p))
9338        *p = toupper(*p);
9339    }
9340  return s;
9341}
9342
9343char *escape_string(char *s)
9344{
9345  char *p, *q;
9346  char string[1024];
9347  char temp[1024];
9348  int i = 0;
9349  int spaces = 0;
9350
9351  if(ActiveDirectory) {
9352    return strdup(s);
9353  }
9354
9355  memset(string, '\0', sizeof(string));
9356
9357  q = s;
9358
9359  /* Escape any special characters */
9360
9361  for(; *q != '\0'; q++) {
9362    if(*q == ',')
9363      string[i++] = '\\';
9364    if(*q == '+')
9365      string[i++] = '\\';
9366    if(*q == '"')
9367      string[i++] = '\\';
9368    if(*q == '\\')
9369      string[i++] = '\\';
9370    if(*q == '<')
9371      string[i++] = '\\';
9372    if(*q == '>')
9373      string[i++] = '\\';
9374    if(*q == ';')
9375      string[i++] = '\\';
9376    if(*q == '#')
9377      string[i++] = '\\';
9378    if(*q == '=')
9379      string[i++] = '\\';
9380
9381    string[i++] = *q;
9382  }
9383
9384  return strdup(string);
9385}
9386
9387int save_query_info(int argc, char **argv, void *hint)
9388{
9389  int i;
9390  char **nargv = hint;
9391
9392  for(i = 0; i < argc; i++)
9393    nargv[i] = strdup(argv[i]);
9394
9395  return MR_CONT;
9396}
9397
9398int save_fsgroup_info(int argc, char **argv, void *hint)
9399{
9400  int i;
9401  char **nargv = hint;
9402
9403  if(!fsgCount)
9404    {
9405      for(i = 0; i < argc; i++)
9406        nargv[i] = strdup(argv[i]);
9407
9408      fsgCount++;
9409    }
9410
9411  return MR_CONT;
9412}
9413
9414int contains_member(LDAP *ldap_handle, char *dn_path, char *group_name,
9415                    char *UserOu, char *user_name)
9416{
9417  char         search_filter[1024];
9418  char         *attr_array[3];
9419  LK_ENTRY     *group_base;
9420  int          group_count;
9421  int          rc;
9422  char         temp[256];
9423
9424  if(ActiveDirectory)
9425    {
9426      sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
9427    }
9428  else
9429    {
9430      if(!strcmp(UserOu, user_ou))
9431        sprintf(temp, "uid=%s,%s,%s", user_name, UserOu, dn_path);
9432      else
9433        sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
9434    }
9435
9436  group_base = NULL;
9437  group_count = 0;
9438 
9439  sprintf(search_filter, "(&(objectClass=group)(cn=%s)(member=%s))",
9440          group_name, temp);
9441
9442  attr_array[0] = "mitMoiraId";
9443  attr_array[1] = NULL;
9444
9445  if ((rc = linklist_build(ldap_handle, dn_path, search_filter,
9446                           attr_array, &group_base, &group_count,
9447                           LDAP_SCOPE_SUBTREE)) != 0)
9448    {
9449      com_err(whoami, 0, "Unable to check group %s for membership of %s : %s",
9450              group_name, user_name, ldap_err2string(rc));
9451      return(-1);
9452    }
9453         
9454  if (group_count)
9455    {
9456      rc = 1;
9457    }
9458  else
9459    {
9460      rc = 0;
9461    }
9462
9463  linklist_free(group_base);
9464  group_count = 0;
9465  group_base = NULL;
9466
9467  return(rc);
9468}
9469
9470static int sasl_flags = LDAP_SASL_QUIET;
9471static char *sasl_mech = "GSSAPI";
9472
9473/* warning! - the following requires intimate knowledge of sasl.h */
9474static char *default_values[] = {
9475  "", /* SASL_CB_USER         0x4001 */
9476  "", /* SASL_CB_AUTHNAME     0x4002 */
9477  "", /* SASL_CB_LANGUAGE     0x4003 */ /* not used */
9478  "", /* SASL_CB_PASS         0x4004 */
9479  "", /* SASL_CB_ECHOPROMPT   0x4005 */
9480  "", /* SASL_CB_NOECHOPROMPT   0x4005 */
9481  "", /* SASL_CB_CNONCE       0x4007 */
9482  ""  /* SASL_CB_GETREALM     0x4008 */
9483};
9484
9485/* this is so we can use SASL_CB_USER etc. to index into default_values */
9486#define VALIDVAL(n) ((n >= SASL_CB_USER) && (n <= SASL_CB_GETREALM))
9487#define VAL(n) default_values[n-0x4001]
9488
9489static int example_sasl_interact( LDAP *ld, unsigned flags, void *defaults, void *prompts ) {
9490  sasl_interact_t         *interact = NULL;
9491  int                     rc;
9492
9493  if (prompts == NULL) {
9494    return (LDAP_PARAM_ERROR);
9495  }
9496
9497  for (interact = prompts; interact->id != SASL_CB_LIST_END; interact++) {
9498    if (VALIDVAL(interact->id)) {
9499      interact->result = VAL(interact->id);
9500      interact->len = strlen((char *)interact->result);
9501    }
9502  }
9503  return (LDAP_SUCCESS);
9504}
9505
9506int ad_connect(LDAP **ldap_handle, char *ldap_domain, char *dn_path,
9507               char *Win2kPassword, char *Win2kUser, char *default_server,
9508               int connect_to_kdc, char **ServerList, char *ldap_realm,
9509               char *ldap_port)
9510{
9511  int         i;
9512  int         k;
9513  int         Count;
9514  char        *server_name[MAX_SERVER_NAMES];
9515  static char temp[128];
9516  ULONG       version = LDAP_VERSION3;
9517  ULONG       rc;
9518  int         Max_wait_time = 1000;
9519  int         Max_size_limit = LDAP_NO_LIMIT;
9520  LDAPControl **ctrls = NULL;
9521
9522  if (strlen(ldap_domain) == 0)
9523    return(1);
9524
9525  if (strlen(ldap_port) == 0)
9526    return(1);
9527
9528  convert_domain_to_dn(ldap_domain, dn_path);
9529  if (strlen(dn_path) == 0)
9530    return(1);
9531
9532  Count = 0;
9533  while (ServerList[Count] != NULL)
9534    ++Count;
9535
9536  if ((Count == 0) && (connect_to_kdc))
9537    return(1);
9538
9539  for (i = 0; i < Count; i++)
9540    {
9541      if (ServerList[i] == NULL)
9542        continue;
9543
9544      if (((*ldap_handle) = ldap_init(ServerList[i], atoi(ldap_port))) != NULL)
9545        {
9546          rc = ldap_set_option((*ldap_handle), LDAP_OPT_PROTOCOL_VERSION,
9547                               &version);
9548          rc = ldap_set_option((*ldap_handle), LDAP_OPT_TIMELIMIT,
9549                               (void *)&Max_wait_time);
9550          rc = ldap_set_option((*ldap_handle), LDAP_OPT_SIZELIMIT,
9551                               (void *)&Max_size_limit);
9552          rc = ldap_set_option((*ldap_handle), LDAP_OPT_REFERRALS,
9553                               LDAP_OPT_OFF);
9554
9555          rc = ldap_sasl_interactive_bind_ext_s((*ldap_handle), "", sasl_mech,
9556                                                 NULL, NULL, sasl_flags,
9557                                                 example_sasl_interact,
9558                                                 NULL, &ctrls);
9559
9560         
9561          if (rc == LDAP_SUCCESS)
9562            {
9563              if (connect_to_kdc)
9564                {
9565                  if (!ad_server_connect(ServerList[i], ldap_domain))
9566                    {
9567                      printf("ad_server_connect failed\n");
9568                      ldap_unbind_s((*ldap_handle));
9569                      (*ldap_handle) = NULL;
9570                      continue;
9571                    }
9572                }
9573              if (strlen(default_server) == 0)
9574                strcpy(default_server, ServerList[i]);
9575              strcpy(connected_server, ServerList[i]);
9576              break;
9577            }
9578          else
9579            {
9580              (*ldap_handle) = NULL;
9581            }
9582        }
9583    }
9584  if ((*ldap_handle) == NULL)
9585    return(1);
9586  return(0);
9587}
9588
9589int convert_domain_to_dn(char *domain, char *dnp)
9590{
9591  char    *fp;
9592  char    *dp;
9593  char    dn[512];
9594
9595  memset(dn, '\0', sizeof(dn));
9596  strcpy(dn, "dc=");
9597  dp = dn+3;
9598  for (fp = domain; *fp; fp++)
9599    {
9600      if (*fp == '.')
9601        {
9602          strcpy(dp, ",dc=");
9603          dp += 4;
9604        }
9605      else
9606        *dp++ = *fp;
9607    }
9608
9609  strcpy(dnp, dn);
9610  return 0;
9611}
9612
9613void ad_kdc_disconnect()
9614{
9615
9616  if (auth_context != NULL)
9617    {
9618      krb5_auth_con_free(context, auth_context);
9619      if (ap_req.data != NULL)
9620        free(ap_req.data);
9621      krb5_free_cred_contents(context, &creds);
9622      if (credsp != NULL)
9623        krb5_free_creds(context, credsp);
9624    }
9625  credsp = NULL;
9626  auth_context = NULL;
9627  if (context != NULL)
9628    {
9629      if (ccache)
9630        krb5_cc_close(context, ccache);
9631      krb5_free_context(context);
9632    }
9633  close(kdc_socket);
9634
9635}
Note: See TracBrowser for help on using the repository browser.