]> andersk Git - moira.git/blob - incremental/winad/winad.c
Remove user and list sid code.
[moira.git] / incremental / winad / winad.c
1 /* $Header$
2 /* winad.incr arguments examples
3  *
4  * arguments when moira creates the account - ignored by winad.incr since the account is unusable.
5  * users 0 11 #45198 45198 /bin/cmd cmd Last First Middle 0 950000001 2000 121049
6  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, mitid, type, moiraid
7  *
8  * arguments for creating or updating a user account 
9  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF 121058  PathToHomeDir PathToProfileDir username 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
10  * users 11 11 #45206 45206 /bin/cmd cmd Last First Middle 0 950000001 STAFF 121058  PathToHomeDir PathToProfileDir newuser 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
11  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, mitid, type, moiraid
12  *
13  * arguments for deactivating/deleting a user account
14  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF 121058  PathToHomeDir PathToProfileDir username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
15  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF 121058  PathToHomeDir PathToProfileDir username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
16  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, mitid, type, moiraid
17  *
18  * arguments for reactivating a user account
19  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF 121058 username 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF 121058
20  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF 121058 username 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF 121058
21  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, mitid, type, moiraid
22  *
23  * arguments for changing user name
24  * users 11 11 oldusername 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF 121058 PathToHomeDir PathToProfileDir newusername 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
25  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, mitid, type, moiraid
26  *
27  * arguments for expunging a user
28  * users 11 0 username 45198 /bin/cmd cmd Last First Middle 0 950000001 2000 121049
29  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, mitid, type, moiraid
30  *
31  * arguments for creating a "special" group/list
32  * list 0 11 listname 1 1 0 0 0 -1 NONE 0 description 92616
33  *   listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description, moiraid
34  * 
35  * arguments for creating a "mail" group/list
36  * list 0 11 listname 1 1 0 1 0 -1 NONE 0 description 92616
37  *   listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description, moiraid
38  *
39  * arguments for creating a "group" group/list
40  * list 0 11 listname 1 1 0 0 1 -1 NONE 0 description 92616
41  *   listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description, moiraid
42  *
43  * arguments for creating a "group/mail" group/list
44  * list 0 11 listname 1 1 0 1 1 -1 NONE 0 description 92616
45  *   listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description, moiraid
46  *
47  * arguments to add a USER member to group/list
48  * imembers 0 12 listname USER userName 1 1 0 0 0 -1 1 92616 121047
49  *   list_name, user_type, name, active, publicflg, hidden, maillist, grouplist, gid, userStatus, moiraListId, moiraUserId
50  *
51  * arguments to add a STRING or KERBEROS member to group/list
52  * imembers 0 10 listname STRING stringName 1 1 0 0 0 -1 92616
53  * imembers 0 10 listlistnameName KERBEROS kerberosName 1 1 0 0 0 -1 92616
54  *   list_name, user_type, name, active, publicflg, hidden, maillist, grouplist, gid, moiraListId
55  *
56  * NOTE: group members of type LIST are ignored.
57  *
58  * arguments to remove a USER member to group/list
59  * imembers 12 0 listname USER userName 1 1 0 0 0 -1 1 92616 121047
60  *   list_name, user_type, name, active, publicflg, hidden, maillist, grouplist, gid, userStatus, moiraListId, moiraUserId
61  *
62  * arguments to remove a STRING or KERBEROS member to group/list
63  * imembers 10 0 listname STRING stringName 1 1 0 0 0 -1 92616
64  * imembers 10 0 listname KERBEROS kerberosName 1 1 0 0 0 -1 92616
65  *   list_name, user_type, name, active, publicflg, hidden, maillist, grouplist, gid, moiraListId
66  *
67  * NOTE: group members of type LIST are ignored.
68  *
69  * arguments for renaming a group/list
70  * list 11 11 oldlistname 1 1 0 0 0 -1 NONE 0 description 92616 newlistname 1 1 0 0 0 -1 description 0 92616
71  *   name, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description, moiraListId
72  *
73  * arguments for deleting a group/list
74  * list 11 0 listname 1 1 0 0 0 -1 NONE 0 description 92616
75  *   name, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description, moiraListId
76  *
77  * arguments for adding a file system
78  * filesys 0 12 username AFS ATHENA.MIT.EDU /afs/athena.mit.edu/user/n/e/username /mit/username w descripton username wheel 1 HOMEDIR 101727
79  *
80  * arguments for deleting a file system
81  * filesys 12 0 username AFS ATHENA.MIT.EDU /afs/athena.mit.edu/user/n/e/username /mit/username w descripton username wheel 1 HOMEDIR 101727
82  *
83  * arguments when moira creates a container (OU).
84  * containers 0 8 machines/test/bottom description location contact USER 105316 2222 [none]
85  *
86  * arguments when moira deletes a container (OU).
87  * containers 8 0 machines/test/bottom description location contact USER 105316 2222 groupname
88  *
89  * arguments when moira modifies a container information (OU).
90  * containers 8 8 machines/test/bottom description location contact USER 105316 2222 groupname machines/test/bottom description1 location contact USER 105316 2222 groupname
91  *
92  * arguments when moira adds a machine from an OU
93  * table name, beforec, afterc, machine_name, container_name, mach_id, cnt_id
94  * mcntmap 0 5 DAVIDT.MIT.EDU dttest/dttest1 76767 46 groupname
95  *
96  * arguments when moira removes a machine from an OU
97  * table name, beforec, afterc, machine_name, container_name, mach_id, cnt_id
98  * mcntmap 0 5 DAVIDT.MIT.EDU dttest/dttest1 76767 46 groupname
99  *
100 */
101 #include <mit-copyright.h>
102 #ifdef _WIN32
103 #include <winsock2.h>
104 #include <windows.h>
105 #include <stdlib.h>
106 #include <malloc.h>
107 #include <lmaccess.h>
108 #endif
109 #include <hesiod.h>
110 #include <string.h>
111 #include <ldap.h>
112 #include <stdio.h>
113 #include <moira.h>
114 #include <moira_site.h>
115 #include <mrclient.h>
116 #include <krb5.h>
117 #include <gsssasl.h>
118 #include <gssldap.h>
119 #include "kpasswd.h"
120
121 #ifdef _WIN32
122 #ifndef ECONNABORTED
123 #define ECONNABORTED WSAECONNABORTED
124 #endif
125 #ifndef ECONNREFUSED
126 #define ECONNREFUSED WSAECONNREFUSED
127 #endif
128 #ifndef EHOSTUNREACH
129 #define EHOSTUNREACH WSAEHOSTUNREACH
130 #endif
131 #define krb5_xfree free
132 #define F_OK 0
133 #define sleep(A) Sleep(A * 1000);
134 #endif /* _WIN32 */
135
136 #ifndef _WIN32
137 #include <sys/types.h>
138 #include <netinet/in.h>
139 #include <arpa/nameser.h>
140 #include <resolv.h>
141 #include <sys/utsname.h>
142 #include <unistd.h>
143
144 #define WINADCFG "/moira/winad/winad.cfg"
145 #define strnicmp(A,B,C) strncasecmp(A,B,C)
146 #define UCHAR unsigned char
147
148 #define UF_SCRIPT               0x0001
149 #define UF_ACCOUNTDISABLE       0x0002
150 #define UF_HOMEDIR_REQUIRED     0x0008
151 #define UF_LOCKOUT              0x0010
152 #define UF_PASSWD_NOTREQD       0x0020
153 #define UF_PASSWD_CANT_CHANGE   0x0040
154 #define UF_DONT_EXPIRE_PASSWD   0x10000
155
156 #define UF_TEMP_DUPLICATE_ACCOUNT       0x0100
157 #define UF_NORMAL_ACCOUNT               0x0200
158 #define UF_INTERDOMAIN_TRUST_ACCOUNT    0x0800
159 #define UF_WORKSTATION_TRUST_ACCOUNT    0x1000
160 #define UF_SERVER_TRUST_ACCOUNT         0x2000
161
162 #define OWNER_SECURITY_INFORMATION       (0x00000001L)
163 #define GROUP_SECURITY_INFORMATION       (0x00000002L)
164 #define DACL_SECURITY_INFORMATION        (0x00000004L)
165 #define SACL_SECURITY_INFORMATION        (0x00000008L)
166
167 #ifndef BYTE
168 #define BYTE unsigned char
169 #endif
170 typedef unsigned int DWORD;
171 typedef unsigned long ULONG;
172
173 typedef struct _GUID
174 {
175   unsigned long Data1;
176   unsigned short Data2;
177   unsigned short Data3;
178   unsigned char Data4[8];
179 } GUID;
180
181 typedef struct _SID_IDENTIFIER_AUTHORITY { 
182   BYTE Value[6]; 
183 } SID_IDENTIFIER_AUTHORITY, *PSID_IDENTIFIER_AUTHORITY; 
184
185 typedef struct _SID {
186   BYTE  Revision;
187   BYTE  SubAuthorityCount;
188   SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
189   DWORD SubAuthority[512];
190 } SID;
191 #endif/*!WIN32*/
192
193 #ifndef WINADCFG
194 #define WINADCFG "winad.cfg"
195 #endif
196
197 #define AFS "/afs/"
198 #define WINAFS "\\\\afs\\all\\"
199
200 #define ADS_GROUP_TYPE_GLOBAL_GROUP         0x00000002
201 #define ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP   0x00000004
202 #define ADS_GROUP_TYPE_LOCAL_GROUP          0x00000004
203 #define ADS_GROUP_TYPE_UNIVERSAL_GROUP      0x00000008
204 #define ADS_GROUP_TYPE_SECURITY_ENABLED     0x80000000
205
206 #define QUERY_VERSION   -1
207 #define PRIMARY_REALM   "ATHENA.MIT.EDU"
208 #define PRIMARY_DOMAIN  "win.mit.edu"
209 #define PRODUCTION_PRINCIPAL "sms"
210 #define TEST_PRINCIPAL       "smstest"
211
212 #define SUBSTITUTE  1
213 #define REPLACE     2
214
215 #define USERS         0
216 #define GROUPS        1
217
218 #define MEMBER_ADD          1
219 #define MEMBER_REMOVE       2
220 #define MEMBER_CHANGE_NAME  3
221 #define MEMBER_ACTIVATE     4
222 #define MEMBER_DEACTIVATE   5
223 #define MEMBER_CREATE       6
224
225 #define MOIRA_ALL       0x0
226 #define MOIRA_USERS     0x1
227 #define MOIRA_KERBEROS  0x2
228 #define MOIRA_STRINGS   0x4
229 #define MOIRA_LISTS     0x8
230
231 #define CHECK_GROUPS    1
232 #define CLEANUP_GROUPS  2
233
234 #define AD_NO_GROUPS_FOUND        -1
235 #define AD_WRONG_GROUP_DN_FOUND   -2
236 #define AD_MULTIPLE_GROUPS_FOUND  -3
237 #define AD_INVALID_NAME           -4
238 #define AD_LDAP_FAILURE           -5
239 #define AD_INVALID_FILESYS        -6
240 #define AD_NO_ATTRIBUTE_FOUND     -7
241 #define AD_NO_OU_FOUND            -8
242 #define AD_NO_USER_FOUND          -9
243
244 /* container arguments */
245 #define CONTAINER_NAME       0
246 #define CONTAINER_DESC       1
247 #define CONTAINER_LOCATION   2
248 #define CONTAINER_CONTACT    3
249 #define CONTAINER_TYPE       4
250 #define CONTAINER_ID         5
251 #define CONTAINER_ROWID      6
252 #define CONTAINER_GROUP_NAME 7
253
254 /*mcntmap arguments*/
255 #define OU_MACHINE_NAME        0
256 #define OU_CONTAINER_NAME      1
257 #define OU_MACHINE_ID          2
258 #define OU_CONTAINER_ID        3
259 #define OU_CONTAINER_GROUP     4
260
261 typedef struct lk_entry {
262   int     op;
263   int     length;
264   int     ber_value;
265   char    *dn;
266   char    *attribute;
267   char    *value;
268   char    *member;
269   char    *type;
270   char    *list;
271   struct  lk_entry *next;
272 } LK_ENTRY;
273
274 #define STOP_FILE "/moira/winad/nowinad"
275 #define file_exists(file) (access((file), F_OK) == 0)
276
277 #define N_SD_BER_BYTES   5
278 #define LDAP_BERVAL struct berval
279 #define MAX_SERVER_NAMES 32
280
281 #define HIDDEN_GROUP                "HiddenGroup.g"
282 #define HIDDEN_GROUP_WITH_ADMIN     "HiddenGroupWithAdmin.g"
283 #define NOT_HIDDEN_GROUP            "NotHiddenGroup.g"
284 #define NOT_HIDDEN_GROUP_WITH_ADMIN "NotHiddenGroupWithAdmin.g"
285
286 #define ADD_ATTR(t, v, o)               \
287   mods[n] = malloc(sizeof(LDAPMod));    \
288   mods[n]->mod_op = o;  \
289   mods[n]->mod_type = t;                \
290   mods[n++]->mod_values = v
291
292 #define DEL_ATTR(t, o)          \
293   DelMods[i] = malloc(sizeof(LDAPMod)); \
294   DelMods[i]->mod_op = o;       \
295   DelMods[i]->mod_type = t;             \
296   DelMods[i++]->mod_values = NULL
297
298 #define DOMAIN_SUFFIX   "MIT.EDU"
299 #define DOMAIN  "DOMAIN:"
300 #define PRINCIPALNAME  "PRINCIPAL:"
301 #define SERVER  "SERVER:"
302 #define MSSFU   "SFU:"
303 #define SFUTYPE "30"
304
305 char    PrincipalName[128];
306 #ifndef _WIN32
307 #define KRB5CCNAME "KRB5CCNAME=/tmp/krb5cc_winad.incr"
308 #define KRBTKFILE "KRBTKFILE=/tmp/tkt_winad.incr"
309 #define KEYTABFILE "/etc/krb5.keytab"
310 #else
311 #define KRB5CCNAME "KRB5CCNAME=\\tmp\\krb5cc_winad.incr"
312 #define KRBTKFILE "KRBTKFILE=\\tmp\\tkt_winad.incr"
313 #define KEYTABFILE "\\keytabs\\krb5.keytab"
314 #endif
315
316 LK_ENTRY *member_base = NULL;
317 static char tbl_buf[1024];
318 char  kerberos_ou[] = "OU=kerberos,OU=moira";
319 char  contact_ou[] = "OU=strings,OU=moira";
320 char  user_ou[] = "OU=users,OU=moira";
321 char  group_ou_distribution[] = "OU=mail,OU=lists,OU=moira";
322 char  group_ou_root[] = "OU=lists,OU=moira";
323 char  group_ou_security[] = "OU=group,OU=lists,OU=moira";
324 char  group_ou_neither[] = "OU=special,OU=lists,OU=moira";
325 char  group_ou_both[] = "OU=mail,OU=group,OU=lists,OU=moira";
326 char  orphans_machines_ou[] = "OU=Machines,OU=Orphans";
327 char  orphans_other_ou[] = "OU=Other,OU=Orphans";
328 char  security_template_ou[] = "OU=security_templates";
329 char *whoami;
330 char ldap_domain[256];
331 char *ServerList[MAX_SERVER_NAMES];
332 int  mr_connections = 0;
333 int  callback_rc;
334 char default_server[256];
335 static char tbl_buf[1024];
336 int  UseSFU30 = 0;
337 int  NoChangeConfigFile;
338
339 extern int set_password(char *user, char *password, char *domain);
340
341 int ad_get_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
342                 char *group_membership, char *MoiraId, char *attribute,
343                 LK_ENTRY **linklist_base, int *linklist_count,
344               char *rFilter);
345 void AfsToWinAfs(char* path, char* winPath);
346 int ad_connect(LDAP **ldap_handle, char *ldap_domain, char *dn_path, 
347                char *Win2kPassword, char *Win2kUser, char *default_server,
348                int connect_to_kdc, char **ServerList);
349 void ad_kdc_disconnect();
350 int ad_server_connect(char *connectedServer, char *domain);
351 int attribute_update(LDAP *ldap_handle, char *distinguished_name, 
352                       char *attribute_value, char *attribute, char *user_name);
353 int BEREncodeSecurityBits(ULONG uBits, char *pBuffer);
354 int checkADname(LDAP *ldap_handle, char *dn_path, char *Name);
355 void check_winad(void);
356 int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, char *MoiraId);
357 /* containers */
358 int container_adupdate(LDAP *ldap_handle, char *dn_path, char *dName, 
359                        char *distinguishedName, int count, char **av);
360 void container_check(LDAP *ldap_handle, char *dn_path, char *name);
361 int container_create(LDAP *ldap_handle, char *dn_path, int count, char **av);
362 int container_delete(LDAP *ldap_handle, char *dn_path, int count, char **av);
363 int container_get_distinguishedName(LDAP *ldap_handle, char *dn_path, 
364                                      char *distinguishedName, int count, char **av);
365 void container_get_dn(char *src, char *dest);
366 void container_get_name(char *src, char *dest);
367 int container_move_objects(LDAP *ldap_handle, char *dn_path, char *dName);
368 int container_rename(LDAP *ldap_handle, char *dn_path, int beforec, char **before, 
369                      int afterc, char **after);
370 int container_update(LDAP *ldap_handle, char *dn_path, int beforec, char **before,
371                      int afterc, char **after);
372
373 int GetAceInfo(int ac, char **av, void *ptr);
374 int GetServerList(char *ldap_domain, char **MasterServe);
375 int get_group_membership(char *group_membership, char *group_ou, 
376                          int *security_flag, char **av);
377 int get_machine_ou(LDAP *ldap_handle, char *dn_path, char *member, char *machine_ou, char *pPtr);
378 int Moira_container_group_create(char **after);
379 int Moira_container_group_delete(char **before);
380 int Moira_groupname_create(char *GroupName, char *ContainerName,
381                            char *ContainerRowID);
382 int Moira_container_group_update(char **before, char **after);
383 int Moira_process_machine_container_group(char *MachineName, char* groupName,
384                                           int DeleteMachine);
385 int Moira_addGroupToParent(char *origContainerName, char *GroupName);
386 int Moira_getContainerGroup(int ac, char **av, void *ptr);
387 int Moira_getGroupName(char *origContainerName, char *GroupName,
388                        int ParentFlag);
389 int Moira_setContainerGroup(char *ContainerName, char *GroupName);
390 int ProcessAce(LDAP *ldap_handle, char *dn_path, char *group_name, char *Type,
391                int UpdateGroup, int *ProcessGroup);
392 int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
393                   char *group_name, char *group_ou, char *group_membership, 
394                   int group_security_flag, int type);
395 int process_lists(int ac, char **av, void *ptr);
396 int ProcessGroupSecurity(LDAP *ldap_handle, char *dn_path, char *TargetGroupName, 
397                          int HiddenGroup, char *AceType, char *AceName);
398 int ProcessMachineName(int ac, char **av, void *ptr);
399 void ReadConfigFile();
400 void StringTrim(char *StringToTrim);
401 int user_create(int ac, char **av, void *ptr);
402 int user_change_status(LDAP *ldap_handle, char *dn_path, 
403                        char *user_name, char *MoiraId, int operation);
404 int user_delete(LDAP *ldap_handle, char *dn_path, 
405                 char *u_name, char *MoiraId);
406 int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name, 
407                 char *user_name);
408 int user_update(LDAP *ldap_handle, char *dn_path, char *user_name,
409                 char *uid, char *MitId, char *MoiraId, int State,
410                 char *WinHomeDir, char *WinProfileDir);
411 void change_to_lower_case(char *ptr);
412 int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou);
413 int group_create(int ac, char **av, void *ptr);
414 int group_delete(LDAP *ldap_handle, char *dn_path, 
415                  char *group_name, char *group_membership, char *MoiraId);
416 int group_rename(LDAP *ldap_handle, char *dn_path, 
417                  char *before_group_name, char *before_group_membership, 
418                  char *before_group_ou, int before_security_flag, char *before_desc,
419                  char *after_group_name, char *after_group_membership, 
420                  char *after_group_ou, int after_security_flag, char *after_desc,
421                  char *MoiraId, char *filter);
422 int machine_check(LDAP *ldap_handle, char *dn_path, char *machine_name);
423 int machine_GetMoiraContainer(int ac, char **av, void *ptr);
424 int machine_get_moira_container(LDAP *ldap_handle, char *dn_path, char *machine_name, char *container_name);
425 int machine_move_to_ou(LDAP *ldap_handle, char *dn_path, char *MoiraMachineName, char *DestinationOu);
426 int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
427                    char *group_name, char *group_ou, char *group_membership, 
428                    int group_security_flag, int updateGroup);
429 int member_list_build(int ac, char **av, void *ptr);
430 int member_add(LDAP *ldap_handle, char *dn_path, char *group_name, 
431                         char *group_ou, char *group_membership, 
432                         char *user_name, char *pUserOu, char *MoiraId);
433 int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name, 
434                   char *group_ou, char *group_membership, char *user_name,
435                   char *pUserOu, char *MoiraId);
436 int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
437                    char *group_ou, char *group_membership, 
438                    int group_security_flag, char *MoiraId);
439 int SetHomeDirectory(LDAP *ldap_handle, char *user_name, char *DistinguishedName,
440                      char *WinHomeDir, char *WinProfileDir,
441                      char **homedir_v, char **winProfile_v,
442                      char **drives_v, LDAPMod **mods, 
443                      int OpType, int n);
444
445 void SwitchSFU(LDAPMod **mods, int *UseSFU30, int n);
446 int check_string(char *s);
447 int check_container_name(char* s);
448
449 int mr_connect_cl(char *server, char *client, int version, int auth);
450
451 void do_container(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
452              char **before, int beforec, char **after, int afterc);
453 void do_list(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
454              char **before, int beforec, char **after, int afterc);
455 void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname, 
456              char **before, int beforec, char **after, int afterc);
457 void do_member(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
458                char **before, int beforec, char **after, int afterc);
459 void do_mcntmap(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
460                 char **before, int beforec, char **after, int afterc);
461 int linklist_create_entry(char *attribute, char *value,
462                           LK_ENTRY **linklist_entry);
463 int linklist_build(LDAP *ldap_handle, char *dn_path, char *search_exp, 
464                    char **attr_array, LK_ENTRY **linklist_base, 
465                    int *linklist_count, unsigned long ScopeType);
466 void linklist_free(LK_ENTRY *linklist_base);
467
468 int retrieve_attributes(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
469                         char *distinguished_name, LK_ENTRY **linklist_current);
470 int retrieve_entries(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
471                      LK_ENTRY **linklist_base, int *linklist_count);
472 int retrieve_values(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
473                     char *Attribute, char *distinguished_name, 
474                     LK_ENTRY **linklist_current);
475
476 int construct_newvalues(LK_ENTRY *linklist_base, int modvalue_count, 
477                         char *oldValue, char *newValue,
478                         char ***modvalues, int type);
479 void free_values(char **modvalues);
480
481 int convert_domain_to_dn(char *domain, char **bind_path);
482 void get_distinguished_name(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
483                             char *distinguished_name);
484 int moira_disconnect(void);
485 int moira_connect(void);
486 void print_to_screen(const char *fmt, ...);
487 int GetMachineName(char *MachineName);
488 int tickets_get_k5();
489 int get_tickets();
490 int destroy_cache(void);
491 int dest_tkt(void);
492
493 int main(int argc, char **argv)
494 {
495   unsigned long   rc;
496   int             beforec;
497   int             afterc;
498   int             i;
499   int             j;
500   int             OldUseSFU30;
501   char            *table;
502   char            **before;
503   char            **after;
504   LDAP            *ldap_handle;
505   char            dn_path[256];
506
507   whoami = ((whoami = (char *)strrchr(argv[0], '/')) ? whoami+1 : argv[0]);
508
509   if (argc < 4)
510     {
511       com_err(whoami, 0, "Unable to process %s", "argc < 4");
512       exit(1);
513     }
514   beforec = atoi(argv[2]);
515   afterc = atoi(argv[3]);
516
517   if (argc < (4 + beforec + afterc))
518     {
519       com_err(whoami, 0, "Unable to process %s", "argc < (4 + breforec + afterc)");
520       exit(1);
521     }
522
523   table = argv[1];
524   before = &argv[4];
525   after = &argv[4 + beforec];
526
527   if (!strcmp(table, "filesys"))
528     exit(0);
529
530   if (afterc == 0)
531     after = NULL;
532   if (beforec == 0)
533     before = NULL;
534
535   for (i = 1; i < argc; i++)
536     {
537       strcat(tbl_buf, argv[i]);
538       strcat(tbl_buf, " ");
539     }
540   com_err(whoami, 0, "%s", tbl_buf);
541
542   memset(PrincipalName, '\0', sizeof(PrincipalName));
543   memset(ldap_domain, '\0', sizeof(ldap_domain));
544   memset(ServerList, '\0', sizeof(ServerList[0]) * MAX_SERVER_NAMES);
545   UseSFU30 = 0;
546   NoChangeConfigFile = 0;
547
548   check_winad();
549
550   ReadConfigFile();
551   OldUseSFU30 = UseSFU30;
552
553   get_tickets();
554
555   initialize_sms_error_table();
556   initialize_krb_error_table();
557
558   memset(default_server, '\0', sizeof(default_server));
559   memset(dn_path, '\0', sizeof(dn_path));
560   for (i = 0; i < 5; i++)
561     {
562       ldap_handle = (LDAP *)NULL;
563       if (!(rc = ad_connect(&ldap_handle, ldap_domain, dn_path, "", "", 
564                             default_server, 1, ServerList)))
565          break;
566       if (ldap_handle == NULL)
567         {
568           if (!NoChangeConfigFile)
569             {
570               for (j = 0; j < MAX_SERVER_NAMES; j++)
571                 {
572                   if (ServerList[j] != NULL)
573                     {
574                       free(ServerList[j]);
575                       ServerList[j] = NULL;
576                     }
577                 }
578               GetServerList(ldap_domain, ServerList);
579             }
580         }
581     }
582
583   if ((rc) || (ldap_handle == NULL))
584     {
585           critical_alert("incremental", "winad.incr cannot connect to any server in domain %s", ldap_domain);
586       destroy_cache();
587       exit(1);
588     }
589
590   for (i = 0; i < (int)strlen(table); i++)
591     table[i] = tolower(table[i]);
592
593   if (!strcmp(table, "users"))
594     do_user(ldap_handle, dn_path, ldap_domain, before, beforec, after,
595             afterc);
596   else if (!strcmp(table, "list"))
597     do_list(ldap_handle, dn_path, ldap_domain, before, beforec, after,
598             afterc);
599   else if (!strcmp(table, "imembers"))
600     do_member(ldap_handle, dn_path, ldap_domain, before, beforec, after,
601               afterc);
602   else if (!strcmp(table, "containers"))
603     do_container(ldap_handle, dn_path, ldap_domain, before, beforec, after,
604                  afterc);
605   else if (!strcmp(table, "mcntmap"))
606     do_mcntmap(ldap_handle, dn_path, ldap_domain, before, beforec, after,
607                afterc);
608   if (OldUseSFU30 != UseSFU30)
609     {
610       if (!NoChangeConfigFile)
611           GetServerList(ldap_domain, ServerList);
612     }
613   ad_kdc_disconnect();
614   for (i = 0; i < MAX_SERVER_NAMES; i++)
615     {
616       if (ServerList[i] != NULL)
617         {
618           free(ServerList[i]);
619           ServerList[i] = NULL;
620         }
621     }
622   rc = ldap_unbind_s(ldap_handle);
623   destroy_cache();
624   exit(0);
625 }
626
627 void do_mcntmap(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
628                 char **before, int beforec, char **after, int afterc)
629 {
630     char    MoiraContainerName[128];
631     char    ADContainerName[128];
632     char    MachineName[1024];
633     char    OriginalMachineName[1024];
634     long    rc;
635     int     DeleteMachine;
636     char    MoiraContainerGroup[64];
637
638     DeleteMachine = 0;
639     memset(ADContainerName, '\0', sizeof(ADContainerName));
640     memset(MoiraContainerName, '\0', sizeof(MoiraContainerName));
641
642     if ((beforec == 0) && (afterc == 0))
643         return;
644
645     if (rc = moira_connect())
646     {
647         critical_alert("AD incremental",
648                        "Error contacting Moira server : %s",
649                        error_message(rc));
650         return;
651     }
652
653     if ((beforec != 0) && (afterc == 0)) /*remove a machine*/
654     {
655         strcpy(OriginalMachineName, before[OU_MACHINE_NAME]);
656         strcpy(MachineName, before[OU_MACHINE_NAME]);
657         strcpy(MoiraContainerGroup, before[OU_CONTAINER_GROUP]);
658         DeleteMachine = 1;
659         com_err(whoami, 0, "removing machine %s from %s", OriginalMachineName, before[OU_CONTAINER_NAME]);
660     }
661     else if ((beforec == 0) && (afterc != 0)) /*add a machine*/
662     {
663         strcpy(OriginalMachineName, after[OU_MACHINE_NAME]);
664         strcpy(MachineName, after[OU_MACHINE_NAME]);
665         strcpy(MoiraContainerGroup, after[OU_CONTAINER_GROUP]);
666         com_err(whoami, 0, "adding machine %s to container %s", OriginalMachineName, after[OU_CONTAINER_NAME]);
667     }
668     else
669       {
670         moira_disconnect();
671         return;
672       }
673
674     rc = GetMachineName(MachineName);
675     if (strlen(MachineName) == 0)
676     {
677         moira_disconnect();
678         com_err(whoami, 0, "Unable to find alais for machine %s in Moira", OriginalMachineName);
679         return;
680     }
681     Moira_process_machine_container_group(MachineName, MoiraContainerGroup,
682                                           DeleteMachine);
683     if (machine_check(ldap_handle, dn_path, MachineName))
684     {
685         com_err(whoami, 0, "Unable to find machine %s (alias %s) in AD.", OriginalMachineName, MachineName);
686         moira_disconnect();
687         return;
688     }
689     memset(MoiraContainerName, '\0', sizeof(MoiraContainerName));
690     machine_get_moira_container(ldap_handle, dn_path, MachineName, MoiraContainerName);
691     if (strlen(MoiraContainerName) == 0)
692     {
693         com_err(whoami, 0, "Unable to fine machine %s (alias %s) container in Moira - moving to orphans OU.",
694                 OriginalMachineName, MachineName);
695         machine_move_to_ou(ldap_handle, dn_path, MachineName, orphans_machines_ou);
696         moira_disconnect();
697         return;
698     }
699     container_get_dn(MoiraContainerName, ADContainerName);
700     if (MoiraContainerName[strlen(MoiraContainerName) - 1] != '/')
701        strcat(MoiraContainerName, "/");
702     container_check(ldap_handle, dn_path, MoiraContainerName);
703     machine_move_to_ou(ldap_handle, dn_path, MachineName, ADContainerName);
704     moira_disconnect();
705     return;
706 }
707
708 void do_container(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
709              char **before, int beforec, char **after, int afterc)
710 {
711   long rc;
712
713   if ((beforec == 0) && (afterc == 0))
714     return;
715
716   if (rc = moira_connect())
717     {
718       critical_alert("AD incremental", "Error contacting Moira server : %s",
719                      error_message(rc));
720       return;
721     }
722
723   if ((beforec != 0) && (afterc == 0)) /*delete a new container*/
724     {
725       com_err(whoami, 0, "deleting container %s", before[CONTAINER_NAME]);
726       container_delete(ldap_handle, dn_path, beforec, before);
727       Moira_container_group_delete(before);
728       moira_disconnect();
729       return;
730     }
731   if ((beforec == 0) && (afterc != 0)) /*create a container*/
732     {
733       com_err(whoami, 0, "creating container %s", after[CONTAINER_NAME]);
734       container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
735       container_create(ldap_handle, dn_path, afterc, after);
736       Moira_container_group_create(after);
737       moira_disconnect();
738       return;
739     }
740
741   if (strcasecmp(before[CONTAINER_NAME], after[CONTAINER_NAME]))
742     {
743       com_err(whoami, 0, "renaming container %s to %s", before[CONTAINER_NAME], after[CONTAINER_NAME]);
744       container_rename(ldap_handle, dn_path, beforec, before, afterc, after);
745       Moira_container_group_update(before, after);
746       moira_disconnect();
747       return;
748     }
749   com_err(whoami, 0, "updating container %s information", after[CONTAINER_NAME]);
750   container_update(ldap_handle, dn_path, beforec, before, afterc, after);
751   Moira_container_group_update(before, after);
752   moira_disconnect();
753   return;
754 }
755
756 #define L_LIST_DESC 9
757 #define L_LIST_ID   10
758
759 void do_list(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
760              char **before, int beforec, char **after, int afterc)
761 {
762   int   updateGroup;
763   int   ProcessGroup;
764   long  rc;
765   char  group_membership[6];
766   char  list_id[32];
767   int   security_flag;
768   char  filter[128];
769   char  group_ou[256];
770   char  before_list_id[32];
771   char  before_group_membership[1];
772   int   before_security_flag;
773   char  before_group_ou[256];
774   LK_ENTRY *ptr = NULL;
775
776   if (beforec == 0 && afterc == 0)
777     return;
778
779   memset(list_id, '\0', sizeof(list_id));
780   memset(before_list_id, '\0', sizeof(before_list_id));
781   memset(before_group_ou, '\0', sizeof(before_group_ou));
782   memset(before_group_membership, '\0', sizeof(before_group_membership));
783   memset(group_ou, '\0', sizeof(group_ou));
784   memset(group_membership, '\0', sizeof(group_membership));
785   updateGroup = 0;
786
787   if (beforec > L_GID)
788     {
789       if (beforec < L_LIST_ID)
790         return;
791       if (beforec > L_LIST_DESC)
792         {
793           strcpy(before_list_id, before[L_LIST_ID]);
794         }
795       before_security_flag = 0;
796       get_group_membership(before_group_membership, before_group_ou, &before_security_flag, before);
797     }
798   if (afterc > L_GID)
799     {
800       if (afterc < L_LIST_ID)
801         return;
802       if (afterc > L_LIST_DESC)
803         {
804           strcpy(list_id, after[L_LIST_ID]);
805         }
806       security_flag = 0;
807       get_group_membership(group_membership, group_ou, &security_flag, after);
808     }
809
810   if ((beforec == 0) && (afterc == 0)) /*this case should never happen*/
811     return;
812
813   updateGroup = 0;
814   if (beforec)
815     {
816       updateGroup = 1;
817       if ((rc = process_group(ldap_handle, dn_path, before_list_id, before[L_NAME], 
818                               before_group_ou, before_group_membership, 
819                               before_security_flag, CHECK_GROUPS)))
820         {
821           if (rc == AD_NO_GROUPS_FOUND)
822             updateGroup = 0;
823           else
824             {
825               if ((rc == AD_WRONG_GROUP_DN_FOUND) || (rc == AD_MULTIPLE_GROUPS_FOUND))
826                 {
827                   rc = process_group(ldap_handle, dn_path, before_list_id, before[L_NAME], 
828                                      before_group_ou, before_group_membership, 
829                                      before_security_flag, CLEANUP_GROUPS);
830                 }
831               if ((rc != AD_NO_GROUPS_FOUND) && (rc != 0))
832                 {
833                   com_err(whoami, 0, "Unable to process list %s",
834                           before[L_NAME]);
835                   return;
836                 }
837               if (rc == AD_NO_GROUPS_FOUND)
838                 updateGroup = 0;
839             }
840         }
841     }
842   
843   if ((beforec != 0) && (afterc != 0))
844     {
845       if (((strcmp(after[L_NAME], before[L_NAME])) || 
846           ((!strcmp(after[L_NAME], before[L_NAME])) && 
847            (strcmp(before_group_ou, group_ou)))) &&
848           (updateGroup == 1))
849         {
850           com_err(whoami, 0, "Changing list name from %s to %s",
851                   before[L_NAME], after[L_NAME]);
852           if ((strlen(before_group_ou) == 0) || (strlen(before_group_membership) == 0) ||
853               (strlen(group_ou) == 0) || (strlen(group_membership) == 0))
854             {
855               com_err(whoami, 0, "%s", "Unable to find the group OU's");
856               return;
857             }
858           memset(filter, '\0', sizeof(filter));
859           if ((rc = group_rename(ldap_handle, dn_path, 
860                                  before[L_NAME], before_group_membership, 
861                                  before_group_ou, before_security_flag, before[L_LIST_DESC],
862                                  after[L_NAME], group_membership, 
863                                  group_ou, security_flag, after[L_LIST_DESC],
864                                  list_id, filter)))
865             {
866               if (rc != AD_NO_GROUPS_FOUND)
867                 {
868                   com_err(whoami, 0, "Unable to change list name from %s to %s",
869                           before[L_NAME], after[L_NAME]);
870                   return;
871                 }
872               updateGroup = 0;
873             }
874           beforec = 0;
875         }
876       else
877         beforec = 0;
878     }
879
880   if (beforec)
881     {
882       if ((strlen(before_group_ou) == 0) || (strlen(before_group_membership) == 0))
883         {
884           com_err(whoami, 0, "Unable to find the group OU for group %s", before[L_NAME]);
885           return;
886         }
887       com_err(whoami, 0, "Deleting group %s", before[L_NAME]);
888       rc = group_delete(ldap_handle, dn_path, before[L_NAME], 
889                         before_group_membership, before_list_id);
890       return;
891     }
892   if (afterc)
893     {
894       if (!updateGroup)
895         {
896           com_err(whoami, 0, "Creating group %s", after[L_NAME]);
897           if (rc = process_group(ldap_handle, dn_path, list_id, after[L_NAME], 
898                                   group_ou, group_membership, 
899                                   security_flag, CHECK_GROUPS))
900             {
901               if (rc != AD_NO_GROUPS_FOUND)
902                 {
903                   if ((rc == AD_WRONG_GROUP_DN_FOUND) || (rc == AD_MULTIPLE_GROUPS_FOUND))
904                     {
905                       rc = process_group(ldap_handle, dn_path, list_id, after[L_NAME], 
906                                          group_ou, group_membership, 
907                                          security_flag, CLEANUP_GROUPS);
908                     }
909                   if (rc)
910                     {
911                       com_err(whoami, 0, "Unable to create list %s", after[L_NAME]);
912                       return;
913                     }
914                 }
915             }
916         }
917       else
918         com_err(whoami, 0, "Updating group %s information", after[L_NAME]);
919
920       if (rc = moira_connect())
921         {
922           critical_alert("AD incremental",
923                          "Error contacting Moira server : %s",
924                          error_message(rc));
925           return;
926         }
927
928       ProcessGroup = 0;
929       if (ProcessAce(ldap_handle, dn_path, after[L_NAME], "LIST", 0, &ProcessGroup))
930         return;
931       if (ProcessGroup)
932         {
933           if (ProcessAce(ldap_handle, dn_path, after[L_NAME], "LIST", 1, &ProcessGroup))
934             return;
935         }
936       if (make_new_group(ldap_handle, dn_path, list_id, after[L_NAME], 
937                          group_ou, group_membership, security_flag, updateGroup))
938         {
939           moira_disconnect();
940           return;
941         }
942       if (atoi(after[L_ACTIVE]))
943         {
944           populate_group(ldap_handle, dn_path, after[L_NAME], group_ou, 
945                          group_membership, security_flag, list_id);
946         }
947       moira_disconnect();
948     }
949   return;
950 }
951
952 #define LM_EXTRA_ACTIVE   (LM_END)
953 #define LM_EXTRA_PUBLIC   (LM_END+1)
954 #define LM_EXTRA_HIDDEN   (LM_END+2)
955 #define LM_EXTRA_MAILLIST (LM_END+3)
956 #define LM_EXTRA_GROUP    (LM_END+4)
957 #define LM_EXTRA_GID      (LM_END+5)
958 #define LMN_LIST_ID       (LM_END+6)
959 #define LM_LIST_ID        (LM_END+7)
960 #define LM_USER_ID        (LM_END+8)
961 #define LM_EXTRA_END      (LM_END+9)
962
963 void do_member(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
964                char **before, int beforec, char **after, int afterc)
965 {
966   char  group_name[128];
967   char  user_name[128];
968   char  user_type[128];
969   char  moira_list_id[32];
970   char  moira_user_id[32];
971   char  group_membership[1];
972   char  group_ou[256];
973   char  machine_ou[256];
974   char  *args[16];
975   char  **ptr;
976   char  *av[7];
977   char  *call_args[7];
978   char  *pUserOu;
979   char  NewMachineName[1024];
980   int   security_flag;
981   int   rc;
982   int   ProcessGroup;
983
984   pUserOu = NULL;
985   ptr = NULL;
986   memset(moira_list_id, '\0', sizeof(moira_list_id));
987   memset(moira_user_id, '\0', sizeof(moira_user_id));
988   if (afterc)
989     {
990       if (afterc < LM_EXTRA_GID)
991         return;
992       if (!atoi(after[LM_EXTRA_ACTIVE]))
993         {
994         com_err(whoami, 0, "Unable to add %s to group %s : group not active", after[2], after[0]);
995         return;
996         }
997       ptr = after;
998       if (!strcasecmp(ptr[LM_TYPE], "LIST"))
999         {
1000           com_err(whoami, 0, "Unable to add %s to group %s : %s is not a group", 
1001                   after[2], after[0], after[0]);
1002           return;
1003         }
1004       strcpy(user_name, after[LM_MEMBER]);
1005       strcpy(group_name, after[LM_LIST]);
1006       strcpy(user_type, after[LM_TYPE]);
1007       if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1008         {
1009           if (afterc > LM_EXTRA_GROUP)
1010             {
1011               strcpy(moira_list_id, after[LMN_LIST_ID]);
1012               strcpy(moira_user_id, after[LM_LIST_ID]);
1013             }
1014         }
1015       else if (!strcasecmp(ptr[LM_TYPE], "USER"))
1016         {
1017           if (afterc > LMN_LIST_ID)
1018             {
1019               strcpy(moira_list_id, after[LM_LIST_ID]);
1020               strcpy(moira_user_id, after[LM_USER_ID]);
1021             }
1022         }
1023       else
1024         {
1025           if (afterc > LM_EXTRA_GID)
1026             strcpy(moira_list_id, after[LMN_LIST_ID]);
1027         }
1028     }
1029   else if (beforec)
1030     {
1031       if (beforec < LM_EXTRA_GID)
1032         return;
1033       if (!atoi(before[LM_EXTRA_ACTIVE]))
1034         {
1035           com_err(whoami, 0, "Unable to add %s to group %s : group not active", before[2], before[0]);
1036           return;
1037         }
1038       ptr = before;
1039       if (!strcasecmp(ptr[LM_TYPE], "LIST"))
1040         {
1041           com_err(whoami, 0, "Unable to add %s to group %s : %s is not a group", 
1042                   before[2], before[0], before[0]);
1043           return;
1044         }
1045       strcpy(user_name, before[LM_MEMBER]);
1046       strcpy(group_name, before[LM_LIST]);
1047       strcpy(user_type, before[LM_TYPE]);
1048       if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1049         {
1050           if (beforec > LM_EXTRA_GROUP)
1051             {
1052               strcpy(moira_list_id, before[LMN_LIST_ID]);
1053               strcpy(moira_user_id, before[LM_LIST_ID]);
1054             }
1055         }
1056       else if (!strcasecmp(ptr[LM_TYPE], "USER"))
1057         {
1058           if (beforec > LMN_LIST_ID)
1059             {
1060               strcpy(moira_list_id, before[LM_LIST_ID]);
1061               strcpy(moira_user_id, before[LM_USER_ID]);
1062             }
1063         }
1064       else
1065         {
1066           if (beforec > LM_EXTRA_GID)
1067             strcpy(moira_list_id, before[LMN_LIST_ID]);
1068         }
1069     }
1070
1071   if (ptr == NULL)
1072     {
1073       com_err(whoami, 0, "Unable to process group : beforec = %d, afterc = %d", beforec, afterc);
1074       return;
1075     }
1076
1077   args[L_NAME] = ptr[LM_LIST];
1078   args[L_ACTIVE] = ptr[LM_EXTRA_ACTIVE];
1079   args[L_PUBLIC] = ptr[LM_EXTRA_PUBLIC];
1080   args[L_HIDDEN] = ptr[LM_EXTRA_HIDDEN];
1081   args[L_MAILLIST] = ptr[LM_EXTRA_MAILLIST];
1082   args[L_GROUP] = ptr[LM_EXTRA_GROUP];
1083   args[L_GID] = ptr[LM_EXTRA_GID];
1084
1085   security_flag = 0;
1086   memset(group_ou, '\0', sizeof(group_ou));
1087   get_group_membership(group_membership, group_ou, &security_flag, args);
1088   if (strlen(group_ou) == 0)
1089     {
1090       com_err(whoami, 0, "Unable to find the group OU for group %s", group_name);
1091       return;
1092     }
1093   if (rc = process_group(ldap_handle, dn_path, moira_list_id, group_name, group_ou, group_membership, security_flag, CHECK_GROUPS))
1094     {
1095       if (rc != AD_NO_GROUPS_FOUND)
1096         {
1097           if (rc = process_group(ldap_handle, dn_path, moira_list_id, group_name, group_ou, group_membership, security_flag, CLEANUP_GROUPS))
1098             {
1099               if (rc != AD_NO_GROUPS_FOUND)
1100                 {
1101                   if (afterc)
1102                     com_err(whoami, 0, "Unable to add %s to group %s - unable to process group", user_name, group_name);
1103                   else
1104                     com_err(whoami, 0, "Unable to remove %s from group %s - unable to process group", user_name, group_name);
1105                   return;
1106                 }
1107             }
1108         }
1109     }
1110   if (rc == AD_NO_GROUPS_FOUND)
1111     {
1112       if (rc = moira_connect())
1113         {
1114           critical_alert("AD incremental",
1115                          "Error contacting Moira server : %s",
1116                          error_message(rc));
1117           return;
1118         }
1119
1120       com_err(whoami, 0, "creating group %s", group_name);
1121       ProcessGroup = 0;
1122       if (ProcessAce(ldap_handle, dn_path, ptr[LM_LIST], "LIST", 0, &ProcessGroup))
1123         return;
1124       if (ProcessGroup)
1125         {
1126           if (ProcessAce(ldap_handle, dn_path, ptr[LM_LIST], "LIST", 1, &ProcessGroup))
1127             return;
1128         }
1129       if (make_new_group(ldap_handle, dn_path, moira_list_id, ptr[LM_LIST], 
1130                          group_ou, group_membership, security_flag, 0))
1131         {
1132           moira_disconnect();
1133           return;
1134         }
1135       if (atoi(ptr[LM_EXTRA_ACTIVE]))
1136         {
1137           populate_group(ldap_handle, dn_path, ptr[LM_LIST], group_ou, 
1138                          group_membership, security_flag, moira_list_id);
1139         }
1140       moira_disconnect();
1141     }
1142   rc = 0;
1143   if (beforec)
1144     {
1145       com_err(whoami, 0, "removing user %s from list %s", user_name, group_name);
1146       pUserOu = user_ou;
1147       if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1148         {
1149           memset(machine_ou, '\0', sizeof(machine_ou));
1150           memset(NewMachineName, '\0', sizeof(NewMachineName));
1151           if (get_machine_ou(ldap_handle, dn_path, ptr[LM_MEMBER], machine_ou, NewMachineName))
1152             return;
1153           ptr[LM_MEMBER] = NewMachineName;
1154           pUserOu = machine_ou;
1155         }
1156       if (!strcasecmp(ptr[LM_TYPE], "STRING"))
1157         {
1158           if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], contact_ou))
1159             return;
1160           pUserOu = contact_ou;
1161         }
1162       else if (!strcasecmp(ptr[LM_TYPE], "KERBEROS"))
1163         {
1164           if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], kerberos_ou))
1165             return;
1166           pUserOu = kerberos_ou;
1167         }
1168       if (rc = member_remove(ldap_handle, dn_path, group_name,
1169                              group_ou, group_membership, ptr[LM_MEMBER], 
1170                              pUserOu, moira_list_id))
1171           com_err(whoami, 0, "Unable to remove %s from group %s", user_name, group_name);
1172       return;
1173     }
1174
1175   com_err(whoami, 0, "Adding %s to list %s", user_name, group_name);
1176   pUserOu = user_ou;
1177
1178   if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1179     {
1180       memset(machine_ou, '\0', sizeof(machine_ou));
1181       memset(NewMachineName, '\0', sizeof(NewMachineName));
1182       if (get_machine_ou(ldap_handle, dn_path, ptr[LM_MEMBER], machine_ou, NewMachineName))
1183         return;
1184       ptr[LM_MEMBER] = NewMachineName;
1185       pUserOu = machine_ou;
1186     }
1187   else if (!strcasecmp(ptr[LM_TYPE], "STRING"))
1188     {
1189       if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], contact_ou))
1190         return;
1191       pUserOu = contact_ou;
1192     }
1193   else if (!strcasecmp(ptr[LM_TYPE], "KERBEROS"))
1194     {
1195       if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], kerberos_ou))
1196         return;
1197       pUserOu = kerberos_ou;
1198     }
1199   else if (!strcasecmp(ptr[LM_TYPE], "USER"))
1200     {
1201       if ((rc = check_user(ldap_handle, dn_path, ptr[LM_MEMBER], 
1202                            moira_user_id)) == AD_NO_USER_FOUND)
1203         {
1204           if (rc = moira_connect())
1205             {
1206               critical_alert("AD incremental", 
1207                              "Error connection to Moira : %s",
1208                              error_message(rc));
1209               return;
1210             }
1211           com_err(whoami, 0, "creating user %s", after[U_NAME]);
1212           av[0] = ptr[LM_MEMBER];
1213           call_args[0] = (char *)ldap_handle;
1214           call_args[1] = dn_path;
1215           call_args[2] = moira_user_id;
1216           call_args[3] = NULL;
1217
1218           callback_rc = 0;
1219           if (rc = mr_query("get_user_account_by_login", 1, av, user_create,
1220                             call_args))
1221             {
1222               moira_disconnect();
1223               com_err(whoami, 0, "Unable to create user %s : %s",
1224                       ptr[LM_MEMBER], error_message(rc));
1225               return;
1226             }
1227           if (callback_rc)
1228             {
1229               moira_disconnect();
1230               com_err(whoami, 0, "Unable to create user %s", ptr[LM_MEMBER]);
1231               return;
1232             }
1233         }
1234       else
1235         {
1236           if (rc != 0)
1237             return;
1238         }
1239       pUserOu = user_ou;
1240     }
1241
1242   if (rc = member_add(ldap_handle, dn_path, group_name,
1243                   group_ou, group_membership, ptr[LM_MEMBER],
1244                   pUserOu, moira_list_id))
1245     {
1246       com_err(whoami, 0, "Unable to add %s to group %s", user_name, group_name);
1247     }
1248   return;
1249 }
1250
1251
1252 #define U_USER_ID    10
1253 #define U_HOMEDIR    11
1254 #define U_PROFILEDIR 12
1255
1256 void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname, 
1257              char **before, int beforec, char **after, 
1258              int afterc)
1259 {
1260   int   rc;
1261   char  *av[7];
1262   char  after_user_id[32];
1263   char  before_user_id[32];
1264   char  *call_args[7];
1265
1266   if ((beforec == 0) && (afterc == 0))
1267     return;
1268
1269   memset(after_user_id, '\0', sizeof(after_user_id));
1270   memset(before_user_id, '\0', sizeof(before_user_id));
1271   if (beforec > U_USER_ID)
1272     strcpy(before_user_id, before[U_USER_ID]);
1273   if (afterc > U_USER_ID)
1274     strcpy(after_user_id, after[U_USER_ID]);
1275
1276   if ((beforec == 0) && (afterc == 0)) /*this case should never happen */
1277     return;
1278
1279   if ((beforec == 0) && (afterc != 0)) 
1280     {
1281       /*this case only happens when the account*/
1282       /*account is first created but not usable*/
1283       com_err(whoami, 0, "Unable to process user %s because the user account is not yet usable", after[U_NAME]);
1284       return;
1285     }
1286   if ((beforec != 0) && (afterc == 0)) /*this case only happens when the account*/
1287     {                                  /*is expunged*/
1288       if (atoi(before[U_STATE]) == 0)
1289         {
1290           com_err(whoami, 0, "expunging user %s from AD", before[U_NAME]);
1291           user_delete(ldap_handle, dn_path, before[U_NAME], before_user_id);
1292         }
1293       else
1294         {
1295           com_err(whoami, 0, "Unable to process because user %s has been previously expungeded", before[U_NAME]);
1296         }
1297       return;
1298     }
1299
1300   /*process anything that gets here*/
1301   if ((rc = check_user(ldap_handle, dn_path, before[U_NAME], 
1302                        before_user_id)) == AD_NO_USER_FOUND)
1303     {
1304       if (!check_string(after[U_NAME]))
1305         return;
1306       if (rc = moira_connect())
1307         {
1308           critical_alert("AD incremental", 
1309                          "Error connection to Moira : %s",
1310                          error_message(rc));
1311           return;
1312         }
1313       com_err(whoami, 0, "creating user %s", after[U_NAME]);
1314
1315       av[0] = after[U_NAME];
1316       call_args[0] = (char *)ldap_handle;
1317       call_args[1] = dn_path;
1318       call_args[2] = after_user_id;
1319       call_args[3] = NULL;
1320       callback_rc = 0;
1321       if (rc = mr_query("get_user_account_by_login", 1, av, user_create,
1322                         call_args))
1323         {
1324           moira_disconnect();
1325           com_err(whoami, 0, "Unable to create user %s : %s",
1326                   after[U_NAME], error_message(rc));
1327           return;
1328         }
1329       if (callback_rc)
1330         {
1331           moira_disconnect();
1332           com_err(whoami, 0, "Unable to create user %s", after[U_NAME]);
1333           return;
1334         }
1335       return;
1336     }
1337   else
1338     {
1339       if (rc != 0)
1340         return;
1341     }
1342   if (strcmp(before[U_NAME], after[U_NAME]))
1343     {
1344       if ((check_string(before[U_NAME])) && (check_string(after[U_NAME])))
1345         {
1346           com_err(whoami, 0, "changing user %s to %s", 
1347                   before[U_NAME], after[U_NAME]);
1348           if ((rc = user_rename(ldap_handle, dn_path, before[U_NAME], 
1349                                 after[U_NAME])) != LDAP_SUCCESS)
1350             {
1351               return;
1352             }
1353         }
1354     }
1355   com_err(whoami, 0, "updating user %s information", after[U_NAME]);
1356   rc = user_update(ldap_handle, dn_path, after[U_NAME],
1357                    after[U_UID], after[U_MITID], 
1358                    after_user_id, atoi(after[U_STATE]),
1359                    after[U_HOMEDIR], after[U_PROFILEDIR]);
1360   return;
1361 }
1362
1363 int construct_newvalues(LK_ENTRY *linklist_base, int modvalue_count, 
1364                         char *oldValue, char *newValue,
1365                         char ***modvalues, int type)
1366 {
1367   LK_ENTRY    *linklist_ptr;
1368   int         i;
1369   char        *cPtr;
1370
1371   if (((*modvalues) = calloc(1, (modvalue_count + 1) * sizeof(char *)))
1372       == NULL)
1373     {
1374       return(1);
1375     }
1376   for (i = 0; i < (modvalue_count + 1); i++)
1377     (*modvalues)[i] = NULL;
1378   if (modvalue_count != 0)
1379     {
1380       linklist_ptr = linklist_base;
1381       for (i = 0; i < modvalue_count; i++)
1382         {
1383           if ((oldValue != NULL) && (newValue != NULL))
1384             {
1385               if ((cPtr = (char *)strstr(linklist_ptr->value, oldValue))
1386                  != (char *)NULL)
1387                 {
1388                   if (type == REPLACE)
1389                     {
1390                       if (((*modvalues)[i] = calloc(1, strlen(newValue) + 1))
1391                           == NULL)
1392                         return(1);
1393                       memset((*modvalues)[i], '\0', strlen(newValue) + 1);
1394                       strcpy((*modvalues)[i], newValue);
1395                     }
1396                   else
1397                     {
1398                       if (((*modvalues)[i] = calloc(1, 
1399                                         (int)(cPtr - linklist_ptr->value) + 
1400                                         (linklist_ptr->length - strlen(oldValue)) + 
1401                                         strlen(newValue) + 1)) == NULL)
1402                         return(1);
1403                       memset((*modvalues)[i], '\0', 
1404                              (int)(cPtr - linklist_ptr->value) + 
1405                              (linklist_ptr->length - strlen(oldValue)) + 
1406                              strlen(newValue) + 1);
1407                       memcpy((*modvalues)[i], linklist_ptr->value, 
1408                              (int)(cPtr - linklist_ptr->value));
1409                       strcat((*modvalues)[i], newValue);
1410                       strcat((*modvalues)[i], 
1411      &linklist_ptr->value[(int)(cPtr - linklist_ptr->value) + strlen(oldValue)]);
1412                     }
1413                 }
1414               else
1415                 {
1416                   (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
1417                   memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
1418                   memcpy((*modvalues)[i], linklist_ptr->value,
1419                          linklist_ptr->length);
1420                 }
1421             }
1422         else
1423             {
1424               (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
1425               memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
1426               memcpy((*modvalues)[i], linklist_ptr->value,
1427                      linklist_ptr->length);
1428             }
1429           linklist_ptr = linklist_ptr->next;
1430         }
1431       (*modvalues)[i] = NULL;
1432     }
1433   return(0);
1434 }
1435
1436
1437 int linklist_build(LDAP *ldap_handle, char *dn_path, char *search_exp, 
1438                    char **attr_array, LK_ENTRY **linklist_base,
1439                    int *linklist_count, unsigned long ScopeType)
1440 {
1441   ULONG       rc;
1442   LDAPMessage *ldap_entry;
1443
1444   rc = 0;
1445   ldap_entry = NULL;
1446   (*linklist_base) = NULL;
1447   (*linklist_count) = 0;
1448   if ((rc = ldap_search_s(ldap_handle, dn_path, ScopeType, 
1449                           search_exp, attr_array, 0, &ldap_entry))
1450       != LDAP_SUCCESS)
1451       {
1452         if (rc != LDAP_SIZELIMIT_EXCEEDED)
1453           return(0);
1454       }
1455
1456   rc = retrieve_entries(ldap_handle, ldap_entry, linklist_base, linklist_count);
1457
1458   ldap_msgfree(ldap_entry);
1459   return(rc);
1460 }
1461
1462
1463 int retrieve_entries(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
1464                      LK_ENTRY **linklist_base, int *linklist_count)
1465 {
1466   char        distinguished_name[1024];
1467   LK_ENTRY    *linklist_ptr;
1468   int         rc;
1469
1470   if ((ldap_entry = ldap_first_entry(ldap_handle, ldap_entry)) == NULL)
1471     return(0);
1472
1473   memset(distinguished_name, '\0', sizeof(distinguished_name));
1474   get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
1475
1476   if ((rc = retrieve_attributes(ldap_handle, ldap_entry, distinguished_name,
1477                                 linklist_base)) != 0)
1478     return(rc);
1479
1480   while ((ldap_entry = ldap_next_entry(ldap_handle, ldap_entry)) != NULL)
1481     {
1482       memset(distinguished_name, '\0', sizeof(distinguished_name));
1483       get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
1484
1485       if ((rc = retrieve_attributes(ldap_handle, ldap_entry, distinguished_name,
1486                                     linklist_base)) != 0)
1487         return(rc);
1488     }
1489
1490   linklist_ptr = (*linklist_base);
1491   (*linklist_count) = 0;
1492   while (linklist_ptr != NULL)
1493     {
1494       ++(*linklist_count);
1495       linklist_ptr = linklist_ptr->next;
1496     }
1497   return(0);
1498 }
1499
1500 int retrieve_attributes(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
1501                         char *distinguished_name, LK_ENTRY **linklist_current)
1502 {
1503   char        *Attribute;
1504   BerElement  *ptr;
1505
1506   ptr = NULL;
1507   if ((Attribute = ldap_first_attribute(ldap_handle, ldap_entry, &ptr)) != NULL)
1508     {
1509       retrieve_values(ldap_handle, ldap_entry, Attribute, distinguished_name,
1510                       linklist_current);
1511       ldap_memfree(Attribute);
1512       while ((Attribute = ldap_next_attribute(ldap_handle, ldap_entry, 
1513                                               ptr)) != NULL)
1514         {
1515           retrieve_values(ldap_handle, ldap_entry, Attribute,
1516                           distinguished_name, linklist_current);
1517           ldap_memfree(Attribute);
1518         }
1519     }
1520   ldap_ber_free(ptr, 0);
1521   return(0);
1522 }
1523
1524 int retrieve_values(LDAP *ldap_handle, LDAPMessage *ldap_entry,
1525                     char *Attribute, char *distinguished_name,
1526                     LK_ENTRY **linklist_current)
1527 {
1528   char        **str_value;
1529   char        temp[256];
1530   void        **Ptr;
1531   int         use_bervalue;
1532   LK_ENTRY    *linklist_previous;
1533   LDAP_BERVAL **ber_value;
1534   DWORD       ber_length;
1535 #ifdef LDAP_DEBUG
1536   SID         *sid;
1537   GUID        *guid;
1538   int         i;
1539   int         intValue;
1540   DWORD       *subauth;
1541   SID_IDENTIFIER_AUTHORITY    *sid_auth;
1542   unsigned char   *subauth_count;
1543 #endif /*LDAP_BEGUG*/
1544
1545   use_bervalue = 0;
1546   memset(temp, '\0', sizeof(temp));
1547   if ((!strcmp(Attribute, "objectSid")) ||
1548       (!strcmp(Attribute, "objectGUID")))
1549     use_bervalue = 1;
1550
1551   if (use_bervalue)
1552     {
1553       ber_value = ldap_get_values_len(ldap_handle, ldap_entry, Attribute);
1554       Ptr = (void **)ber_value;
1555       str_value = NULL;
1556       }
1557   else
1558     {
1559       str_value = ldap_get_values(ldap_handle, ldap_entry, Attribute);
1560       Ptr = (void **)str_value;
1561       ber_value = NULL;
1562     }
1563   if (Ptr != NULL)
1564     {
1565       for (; *Ptr; Ptr++) 
1566         {
1567           if ((linklist_previous = calloc(1, sizeof(LK_ENTRY))) == NULL)
1568             return(1);
1569           memset(linklist_previous, '\0', sizeof(LK_ENTRY));
1570           linklist_previous->next = (*linklist_current);
1571           (*linklist_current) = linklist_previous;
1572
1573           if (((*linklist_current)->attribute = calloc(1, 
1574                                                strlen(Attribute) + 1)) == NULL)
1575             return(1);
1576           memset((*linklist_current)->attribute, '\0', strlen(Attribute) + 1);
1577           strcpy((*linklist_current)->attribute, Attribute);
1578           if (use_bervalue)
1579             {
1580               ber_length = (*(LDAP_BERVAL **)Ptr)->bv_len;
1581               if (((*linklist_current)->value = calloc(1, ber_length)) == NULL)
1582                 return(1);
1583               memset((*linklist_current)->value, '\0', ber_length);
1584               memcpy((*linklist_current)->value, (*(LDAP_BERVAL **)Ptr)->bv_val, 
1585                                                   ber_length);
1586               (*linklist_current)->length = ber_length;
1587             }
1588           else
1589             {
1590               if (((*linklist_current)->value = calloc(1, 
1591                                                   strlen(*Ptr) + 1)) == NULL)
1592                 return(1);
1593               memset((*linklist_current)->value, '\0', strlen(*Ptr) + 1);
1594               (*linklist_current)->length = strlen(*Ptr);
1595               strcpy((*linklist_current)->value, *Ptr);
1596             }
1597           (*linklist_current)->ber_value = use_bervalue;
1598           if (((*linklist_current)->dn = calloc(1, 
1599                                       strlen(distinguished_name) + 1)) == NULL)
1600             return(1);
1601           memset((*linklist_current)->dn, '\0', strlen(distinguished_name) + 1);
1602           strcpy((*linklist_current)->dn, distinguished_name);
1603
1604 #ifdef LDAP_DEBUG
1605           if (!strcmp(Attribute, "objectGUID"))
1606             {
1607               guid = (GUID *)((*linklist_current)->value);
1608               sprintf(temp, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 
1609                       guid->Data1, guid->Data2, guid->Data3, 
1610                       guid->Data4[0], guid->Data4[1], guid->Data4[2], 
1611                       guid->Data4[3], guid->Data4[4], guid->Data4[5], 
1612                       guid->Data4[6], guid->Data4[7]);
1613               print_to_screen("     %20s : {%s}\n", Attribute, temp);
1614             }
1615           else if (!strcmp(Attribute, "objectSid"))
1616             {
1617               sid = (SID *)((*(LDAP_BERVAL **)Ptr)->bv_val);
1618 #ifdef _WIN32
1619               print_to_screen("        Revision = %d\n", sid->Revision);
1620               print_to_screen("        SID Identifier Authority:\n");
1621               sid_auth = &sid->IdentifierAuthority;
1622               if (sid_auth->Value[0])
1623                 print_to_screen("            SECURITY_NULL_SID_AUTHORITY\n");
1624               else if (sid_auth->Value[1])
1625                 print_to_screen("            SECURITY_WORLD_SID_AUTHORITY\n");
1626               else if (sid_auth->Value[2])
1627                 print_to_screen("            SECURITY_LOCAL_SID_AUTHORITY\n");
1628               else if (sid_auth->Value[3])
1629                 print_to_screen("            SECURITY_CREATOR_SID_AUTHORITY\n");
1630               else if (sid_auth->Value[5])
1631                 print_to_screen("            SECURITY_NT_AUTHORITY\n");
1632               else
1633                 print_to_screen("            UNKNOWN SID AUTHORITY\n");
1634               subauth_count = GetSidSubAuthorityCount(sid);
1635               print_to_screen("        SidSubAuthorityCount = %d\n", 
1636                               *subauth_count);
1637               print_to_screen("        SidSubAuthority:\n");
1638               for (i = 0; i < *subauth_count; i++)
1639                 {
1640                   if ((subauth = GetSidSubAuthority(sid, i)) != NULL)
1641                     print_to_screen("            %u\n", *subauth);
1642                 }
1643 #endif
1644             }
1645           else if ((!memcmp(Attribute, "userAccountControl", 
1646                             strlen("userAccountControl"))) ||
1647                    (!memcmp(Attribute, "sAMAccountType", 
1648                             strlen("sAmAccountType"))))
1649             {
1650               intValue = atoi(*Ptr);
1651               print_to_screen("     %20s : %ld\n",Attribute, intValue);
1652               if (!memcmp(Attribute, "userAccountControl", 
1653                           strlen("userAccountControl")))
1654                 {
1655                   if (intValue & UF_ACCOUNTDISABLE)
1656                     print_to_screen("     %20s :    %s\n", 
1657                                     "", "Account disabled");
1658                   else
1659                     print_to_screen("     %20s :    %s\n", 
1660                                     "", "Account active");
1661                   if (intValue & UF_HOMEDIR_REQUIRED)
1662                     print_to_screen("     %20s :    %s\n", 
1663                                     "", "Home directory required");
1664                   if (intValue & UF_LOCKOUT)
1665                     print_to_screen("     %20s :    %s\n", 
1666                                     "", "Account locked out");
1667                   if (intValue & UF_PASSWD_NOTREQD)
1668                     print_to_screen("     %20s :    %s\n", 
1669                                     "", "No password required");
1670                   if (intValue & UF_PASSWD_CANT_CHANGE)
1671                     print_to_screen("     %20s :    %s\n",
1672                                     "", "Cannot change password");
1673                   if (intValue & UF_TEMP_DUPLICATE_ACCOUNT)
1674                     print_to_screen("     %20s :    %s\n", 
1675                                     "", "Temp duplicate account");
1676                   if (intValue & UF_NORMAL_ACCOUNT)
1677                     print_to_screen("     %20s :    %s\n", 
1678                                     "", "Normal account");
1679                   if (intValue & UF_INTERDOMAIN_TRUST_ACCOUNT)
1680                     print_to_screen("     %20s :    %s\n", 
1681                                     "", "Interdomain trust account");
1682                   if (intValue & UF_WORKSTATION_TRUST_ACCOUNT)
1683                     print_to_screen("     %20s :    %s\n", 
1684                                     "", "Workstation trust account");
1685                   if (intValue & UF_SERVER_TRUST_ACCOUNT)
1686                     print_to_screen("     %20s :    %s\n", 
1687                                     "", "Server trust account");
1688                 }
1689             }
1690           else
1691             {
1692               print_to_screen("     %20s : %s\n",Attribute, *Ptr);
1693             }
1694 #endif /*LDAP_DEBUG*/
1695         }
1696       if (str_value != NULL)
1697         ldap_value_free(str_value);
1698       if (ber_value != NULL)
1699         ldap_value_free_len(ber_value);
1700     }
1701   (*linklist_current) = linklist_previous;
1702   return(0);
1703 }
1704
1705 int moira_connect(void)
1706 {
1707   long    rc;
1708   char    HostName[64];
1709
1710   if (!mr_connections++)
1711     {
1712 #ifdef _WIN32
1713       memset(HostName, '\0', sizeof(HostName));
1714       strcpy(HostName, "ttsp");
1715       rc = mr_connect_cl(HostName, "winad.incr", QUERY_VERSION, 1);
1716 /*det
1717       rc = mr_connect(HostName);
1718 */
1719 #else
1720       struct utsname uts;
1721       uname(&uts);
1722       rc = mr_connect_cl(uts.nodename, "winad.incr", QUERY_VERSION, 1);
1723 /*
1724       rc = mr_connect(uts.nodename);
1725 */
1726 #endif /*WIN32*/
1727 /*det
1728       if (!rc)
1729         rc = mr_auth("winad.incr");
1730 */
1731       return rc;
1732     }
1733   return 0;
1734 }
1735
1736 void check_winad(void)
1737 {
1738   int i;
1739   
1740   for (i = 0; file_exists(STOP_FILE); i++)
1741     {
1742       if (i > 30)
1743         {
1744           critical_alert("AD incremental",
1745                          "WINAD incremental failed (%s exists): %s",
1746                          STOP_FILE, tbl_buf);
1747           exit(1);
1748         }
1749       sleep(60);
1750     }
1751 }
1752
1753 int moira_disconnect(void)
1754 {
1755
1756   if (!--mr_connections)
1757     {
1758       mr_disconnect();
1759     }
1760   return 0;
1761 }
1762
1763 void get_distinguished_name(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
1764                             char *distinguished_name)
1765 {
1766   char    *CName;
1767
1768   CName = ldap_get_dn(ldap_handle, ldap_entry);
1769   if (CName == NULL)
1770     return;
1771   strcpy(distinguished_name, CName);
1772   ldap_memfree(CName);
1773 }
1774
1775 int linklist_create_entry(char *attribute, char *value, 
1776                           LK_ENTRY **linklist_entry)
1777 {
1778   (*linklist_entry) = calloc(1, sizeof(LK_ENTRY));
1779   if (!(*linklist_entry))
1780     {
1781       return(1);
1782     }
1783   memset((*linklist_entry), '\0', sizeof(LK_ENTRY));
1784   (*linklist_entry)->attribute = calloc(1, strlen(attribute) + 1);
1785   memset((*linklist_entry)->attribute, '\0', strlen(attribute) + 1);
1786   strcpy((*linklist_entry)->attribute, attribute);
1787   (*linklist_entry)->value = calloc(1, strlen(value) + 1);
1788   memset((*linklist_entry)->value, '\0', strlen(value) + 1);
1789   strcpy((*linklist_entry)->value, value);
1790   (*linklist_entry)->length = strlen(value);
1791   (*linklist_entry)->next = NULL;
1792   return(0);
1793 }
1794
1795 void print_to_screen(const char *fmt, ...)
1796 {
1797   va_list pvar;
1798
1799   va_start(pvar, fmt);
1800   vfprintf(stderr, fmt, pvar);
1801   fflush(stderr);
1802   va_end(pvar);
1803 }
1804
1805 int get_group_membership(char *group_membership, char *group_ou, 
1806                          int *security_flag, char **av)
1807 {
1808   int  maillist_flag;
1809   int  group_flag;
1810
1811   maillist_flag = atoi(av[L_MAILLIST]);
1812   group_flag = atoi(av[L_GROUP]);
1813   if (security_flag != NULL)
1814     (*security_flag) = 0;
1815
1816   if ((maillist_flag) && (group_flag))
1817     {
1818       if (group_membership != NULL)
1819         group_membership[0] = 'B';
1820       if (security_flag != NULL)
1821         (*security_flag) = 1;
1822       if (group_ou != NULL)
1823         strcpy(group_ou, group_ou_both);
1824     }
1825   else if ((!maillist_flag) && (group_flag))
1826     {
1827       if (group_membership != NULL)
1828         group_membership[0] = 'S';
1829       if (security_flag != NULL)
1830         (*security_flag) = 1;
1831       if (group_ou != NULL)
1832         strcpy(group_ou, group_ou_security);
1833     }
1834   else if ((maillist_flag) && (!group_flag))
1835     {
1836       if (group_membership != NULL)
1837         group_membership[0] = 'D';
1838       if (group_ou != NULL)
1839         strcpy(group_ou, group_ou_distribution);
1840     }
1841   else
1842     {
1843       if (group_membership != NULL)
1844         group_membership[0] = 'N';
1845       if (group_ou != NULL)
1846         strcpy(group_ou, group_ou_neither);
1847     }
1848   return(0);
1849 }
1850
1851 int group_rename(LDAP *ldap_handle, char *dn_path, 
1852                  char *before_group_name, char *before_group_membership, 
1853                  char *before_group_ou, int before_security_flag, char *before_desc,
1854                  char *after_group_name, char *after_group_membership, 
1855                  char *after_group_ou, int after_security_flag, char *after_desc,
1856                  char *MoiraId, char *filter)
1857 {
1858   LDAPMod   *mods[20];
1859   char      old_dn[512];
1860   char      new_dn[512];
1861   char      new_dn_path[512];
1862   char      sam_name[256];
1863   char      *attr_array[3];
1864   char      *mitMoiraId_v[] = {NULL, NULL};
1865   char      *name_v[] = {NULL, NULL};
1866   char      *samAccountName_v[] = {NULL, NULL};
1867   char      *groupTypeControl_v[] = {NULL, NULL};
1868   u_int     groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
1869   char      groupTypeControlStr[80];
1870   int       n;
1871   int       i;
1872   int       rc;
1873   LK_ENTRY  *group_base;
1874   int       group_count;
1875
1876   if (!check_string(before_group_name))
1877     {
1878       com_err(whoami, 0, "Unable to process invalid LDAP list name %s", before_group_name);
1879       return(AD_INVALID_NAME);
1880     }
1881   if (!check_string(after_group_name))
1882     {
1883       com_err(whoami, 0, "Unable to process invalid LDAP list name %s", after_group_name);
1884       return(AD_INVALID_NAME);
1885     }
1886
1887   group_count = 0;
1888   group_base = NULL;
1889   if (rc = ad_get_group(ldap_handle, dn_path, before_group_name, 
1890                         before_group_membership, 
1891                         MoiraId, "distinguishedName", &group_base, 
1892                         &group_count, filter))
1893     return(rc);
1894
1895   if (group_count == 0)
1896     {
1897       return(AD_NO_GROUPS_FOUND);
1898     }
1899   if (group_count != 1)
1900     {
1901       com_err(whoami, 0,
1902               "Unable to process multiple groups with MoiraId = %s exist in the AD",
1903               MoiraId);
1904       return(AD_MULTIPLE_GROUPS_FOUND);
1905     }
1906   strcpy(old_dn, group_base->value);
1907
1908   linklist_free(group_base);
1909   group_base = NULL;
1910   group_count = 0;
1911   attr_array[0] = "sAMAccountName";
1912   attr_array[1] = NULL;
1913   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
1914                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
1915     {
1916       com_err(whoami, 0, "Unable to get list %s dn : %s",
1917               after_group_name, ldap_err2string(rc));
1918       return(rc);
1919     }
1920   if (group_count != 1)
1921     {
1922       com_err(whoami, 0,
1923               "Unable to get sAMAccountName for group %s", 
1924               before_group_name);
1925       return(AD_LDAP_FAILURE);
1926     }
1927
1928   strcpy(sam_name, group_base->value);
1929   linklist_free(group_base);
1930   group_base = NULL;
1931   group_count = 0;
1932
1933   sprintf(new_dn_path, "%s,%s", after_group_ou, dn_path);
1934   sprintf(new_dn, "cn=%s", after_group_name);
1935   if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, new_dn_path,
1936                           TRUE, NULL, NULL)) != LDAP_SUCCESS)
1937     {
1938       com_err(whoami, 0, "Unable to rename list from %s to %s : %s",
1939               before_group_name, after_group_name, ldap_err2string(rc));
1940       return(rc);
1941     }
1942
1943   name_v[0] = after_group_name;
1944   if (!strncmp(&sam_name[strlen(sam_name) - strlen("_group")], "_group", strlen("_group")))
1945     {
1946       sprintf(sam_name, "%s_group", after_group_name);
1947     }
1948   else
1949     {
1950       com_err(whoami, 0, "Unable to rename list from %s to %s : sAMAccountName not found",
1951               before_group_name, after_group_name);
1952       return(rc);
1953     }
1954   samAccountName_v[0] = sam_name;
1955   if (after_security_flag)
1956     groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
1957   sprintf(groupTypeControlStr, "%ld", groupTypeControl);
1958   groupTypeControl_v[0] = groupTypeControlStr;
1959   mitMoiraId_v[0] = MoiraId;
1960
1961   sprintf(new_dn, "cn=%s,%s,%s", after_group_name, after_group_ou, dn_path);
1962   rc = attribute_update(ldap_handle, new_dn, after_desc, "description", after_group_name);
1963   n = 0;
1964   ADD_ATTR("samAccountName", samAccountName_v, LDAP_MOD_REPLACE);
1965   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
1966   ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
1967   ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_REPLACE);
1968   mods[n] = NULL;
1969   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
1970     {
1971       com_err(whoami, 0, "Unable to modify list data for %s after renaming: %s",
1972               after_group_name, ldap_err2string(rc));
1973     }
1974   for (i = 0; i < n; i++)
1975     free(mods[i]);
1976   return(rc);
1977 }
1978
1979 int group_create(int ac, char **av, void *ptr)
1980 {
1981   LDAPMod *mods[20];
1982   char new_dn[256];
1983   char group_ou[256];
1984   char new_group_name[256];
1985   char sam_group_name[256];
1986   char cn_group_name[256];
1987   char *cn_v[] = {NULL, NULL};
1988   char *objectClass_v[] = {"top", "group", NULL};
1989   char info[256];
1990   char *samAccountName_v[] = {NULL, NULL};
1991   char *altSecurityIdentities_v[] = {NULL, NULL};
1992   char *member_v[] = {NULL, NULL};
1993   char *name_v[] = {NULL, NULL};
1994   char *desc_v[] = {NULL, NULL};
1995   char *info_v[] = {NULL, NULL};
1996   char *mitMoiraId_v[] = {NULL, NULL};
1997   char *groupTypeControl_v[] = {NULL, NULL};
1998   char groupTypeControlStr[80];
1999   char group_membership[1];
2000   int  i;
2001   int  security_flag;
2002   u_int groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
2003   int  n;
2004   int  rc;
2005   int  updateGroup;
2006   char **call_args;
2007
2008   call_args = ptr;
2009
2010   if (!check_string(av[L_NAME]))
2011     {
2012       com_err(whoami, 0, "Unable to process invalid LDAP list name %s", av[L_NAME]);
2013       return(AD_INVALID_NAME);
2014     }
2015
2016   updateGroup = (int)call_args[4];
2017   memset(group_ou, 0, sizeof(group_ou));
2018   memset(group_membership, 0, sizeof(group_membership));
2019   security_flag = 0;
2020   get_group_membership(group_membership, group_ou, &security_flag, av);
2021   strcpy(new_group_name, av[L_NAME]);
2022   sprintf(new_dn, "cn=%s,%s,%s", new_group_name, group_ou, call_args[1]);
2023   if (security_flag)
2024     groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
2025   
2026   sprintf(sam_group_name, "%s_group", av[L_NAME]);
2027
2028   if (!updateGroup)
2029     {
2030
2031       sprintf(groupTypeControlStr, "%ld", groupTypeControl);
2032       groupTypeControl_v[0] = groupTypeControlStr;
2033
2034       strcpy(cn_group_name, av[L_NAME]);
2035
2036       samAccountName_v[0] = sam_group_name;
2037       name_v[0] = new_group_name;
2038       cn_v[0] = new_group_name;
2039
2040       n = 0;
2041       ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
2042       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2043       ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
2044       ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2045       ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2046       if (strlen(av[L_DESC]) != 0)
2047         {
2048           desc_v[0] = av[L_DESC];
2049           ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2050         }
2051       ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_ADD);
2052       if (strlen(av[L_ACE_NAME]) != 0)
2053         {
2054           sprintf(info, "The Administrator of this list is: %s", av[L_ACE_NAME]);
2055           info_v[0] = info;
2056           ADD_ATTR("info", info_v, LDAP_MOD_ADD);
2057         }
2058       if (strlen(call_args[5]) != 0)
2059         {
2060           mitMoiraId_v[0] = call_args[5];
2061           ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
2062         }
2063       mods[n] = NULL;
2064
2065       rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
2066
2067       for (i = 0; i < n; i++)
2068         free(mods[i]);
2069       if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2070         {
2071           com_err(whoami, 0, "Unable to create list %s in AD : %s",
2072                   av[L_NAME], ldap_err2string(rc));
2073           callback_rc = rc;
2074           return(rc);
2075         }
2076     }
2077   if ((rc == LDAP_ALREADY_EXISTS) || (updateGroup))
2078     {
2079       rc = attribute_update((LDAP *)call_args[0], new_dn, av[L_DESC], "description", av[L_NAME]);
2080       sprintf(info, "The Administrator of this list is: %s", av[L_ACE_NAME]);
2081       rc = attribute_update((LDAP *)call_args[0], new_dn, info, "info", av[L_NAME]);
2082       n = 0;
2083       if (strlen(call_args[5]) != 0)
2084         {
2085           mitMoiraId_v[0] = call_args[5];
2086           ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2087         }
2088       if (!(atoi(av[L_ACTIVE])))
2089         {
2090           member_v[0] = NULL;
2091           ADD_ATTR("member", member_v, LDAP_MOD_REPLACE);
2092         }
2093       mods[n] = NULL;
2094       rc = LDAP_SUCCESS;
2095       if (n != 0)
2096         {
2097           rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
2098           for (i = 0; i < n; i++)
2099               free(mods[i]);
2100           if (rc != LDAP_SUCCESS)
2101             {
2102               com_err(whoami, 0, "Unable to update list %s in AD : %s",
2103                       av[L_NAME], ldap_err2string(rc));
2104               callback_rc = rc;
2105               return(rc);
2106             }
2107         }
2108     }
2109
2110   ProcessGroupSecurity((LDAP *)call_args[0], call_args[1], av[L_NAME], 
2111                        atoi(av[L_HIDDEN]),  av[L_ACE_TYPE], av[L_ACE_NAME]);
2112
2113   return(LDAP_SUCCESS);
2114 }
2115
2116 int ProcessGroupSecurity(LDAP *ldap_handle, char *dn_path, char *TargetGroupName, 
2117                          int HiddenGroup, char *AceType, char *AceName)
2118 {
2119   char          filter_exp[1024];
2120   char          *attr_array[5];
2121   char          search_path[512];
2122   char          root_ou[128];
2123   char          TemplateDn[512];
2124   char          TemplateSamName[128];
2125   char          TargetDn[512];
2126   char          TargetSamName[128];
2127   char          AceSamAccountName[128];
2128   char          AceDn[256];
2129   unsigned char AceSid[128];
2130   unsigned char UserTemplateSid[128];
2131   char          acBERBuf[N_SD_BER_BYTES];
2132   char          GroupSecurityTemplate[256];
2133   int           AceSidCount;
2134   int           UserTemplateSidCount;
2135   int           group_count;
2136   int           n;
2137   int           i;
2138   int           rc;
2139   int           nVal;
2140   ULONG         dwInfo;
2141   int           array_count = 0;
2142   LDAPMod       *mods[20];
2143   LK_ENTRY      *group_base;
2144   LDAP_BERVAL   **ppsValues;
2145   LDAPControl sControl = {"1.2.840.113556.1.4.801",
2146                           { N_SD_BER_BYTES, acBERBuf },
2147                           TRUE
2148                          };
2149   LDAPControl *apsServerControls[] = {&sControl, NULL};
2150   LDAPMessage *psMsg;
2151
2152   dwInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
2153   BEREncodeSecurityBits(dwInfo, acBERBuf);
2154
2155   sprintf(search_path, "%s,%s", group_ou_root, dn_path);
2156   sprintf(filter_exp, "(sAMAccountName=%s_group)", TargetGroupName);
2157   attr_array[0] = "sAMAccountName";
2158   attr_array[1] = NULL;
2159   group_count = 0;
2160   group_base = NULL;
2161   if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
2162                                &group_base, &group_count, LDAP_SCOPE_SUBTREE) != 0))
2163     return(1);
2164   if (group_count != 1)
2165     {
2166       linklist_free(group_base);
2167       return(1);
2168     }
2169   strcpy(TargetDn, group_base->dn);
2170   strcpy(TargetSamName, group_base->value);
2171   linklist_free(group_base);
2172   group_base = NULL;
2173   group_count = 0;
2174
2175   UserTemplateSidCount = 0;
2176   memset(UserTemplateSid, '\0', sizeof(UserTemplateSid));
2177   memset(AceSamAccountName, '\0', sizeof(AceSamAccountName));
2178   memset(AceSid, '\0', sizeof(AceSid));
2179   AceSidCount = 0;
2180   group_base = NULL;
2181   group_count = 0;
2182   if (strlen(AceName) != 0)
2183     {
2184       if (!strcmp(AceType, "LIST"))
2185         {
2186           sprintf(AceSamAccountName, "%s_group", AceName);
2187           strcpy(root_ou, group_ou_root);
2188         }
2189       else if (!strcmp(AceType, "USER"))
2190         {
2191           sprintf(AceSamAccountName, "%s", AceName);
2192           strcpy(root_ou, user_ou);
2193         }
2194       if (strlen(AceSamAccountName) != 0)
2195         {
2196           sprintf(search_path, "%s", dn_path);
2197           sprintf(filter_exp, "(sAMAccountName=%s)", AceSamAccountName);
2198           attr_array[0] = "objectSid";
2199           attr_array[1] = NULL;
2200           group_count = 0;
2201           group_base = NULL;
2202           if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
2203                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE) != 0))
2204             return(1);
2205           if (group_count == 1)
2206             {
2207               strcpy(AceDn, group_base->dn);
2208               AceSidCount = group_base->length;
2209               memcpy(AceSid, group_base->value, AceSidCount);
2210             }
2211           linklist_free(group_base);
2212           group_base = NULL;
2213           group_count = 0;
2214         }
2215     }
2216   if (AceSidCount == 0)
2217     {
2218       com_err(whoami, 0, "Group %s: Administrator: %s, Type: %s - does not have an AD SID.", TargetGroupName, AceName, AceType);
2219       com_err(whoami, 0, "   Non-admin security group template will be used.");
2220     }
2221   else
2222     {
2223       sprintf(search_path, "%s,%s", security_template_ou, dn_path);
2224       sprintf(filter_exp, "(sAMAccountName=%s)", "UserTemplate.u");
2225       attr_array[0] = "objectSid";
2226       attr_array[1] = NULL;
2227
2228       group_count = 0;
2229       group_base = NULL;
2230       if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
2231                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE) != 0))
2232         return(1);
2233       if ((rc != 0) || (group_count != 1))
2234         {
2235           com_err(whoami, 0, "Unable to process user security template: %s", "UserTemplate");
2236           AceSidCount = 0;
2237         }
2238       else
2239         {
2240           UserTemplateSidCount = group_base->length;
2241           memcpy(UserTemplateSid, group_base->value, UserTemplateSidCount);
2242         }
2243       linklist_free(group_base);
2244       group_base = NULL;
2245       group_count = 0;
2246     }
2247
2248   if (HiddenGroup)
2249     {
2250       if (AceSidCount == 0)
2251         {
2252           strcpy(GroupSecurityTemplate, HIDDEN_GROUP);
2253           sprintf(filter_exp, "(sAMAccountName=%s)", HIDDEN_GROUP);
2254         }
2255       else
2256         {
2257           strcpy(GroupSecurityTemplate, HIDDEN_GROUP_WITH_ADMIN);
2258           sprintf(filter_exp, "(sAMAccountName=%s)", HIDDEN_GROUP_WITH_ADMIN);
2259         }
2260     }
2261   else
2262     {
2263       if (AceSidCount == 0)
2264         {
2265           strcpy(GroupSecurityTemplate, NOT_HIDDEN_GROUP);
2266           sprintf(filter_exp, "(sAMAccountName=%s)", NOT_HIDDEN_GROUP);
2267         }
2268       else
2269         {
2270           strcpy(GroupSecurityTemplate, NOT_HIDDEN_GROUP_WITH_ADMIN);
2271           sprintf(filter_exp, "(sAMAccountName=%s)", NOT_HIDDEN_GROUP_WITH_ADMIN);
2272         }
2273     }
2274
2275   sprintf(search_path, "%s,%s", security_template_ou, dn_path);
2276   attr_array[0] = "sAMAccountName";
2277   attr_array[1] = NULL;
2278   group_count = 0;
2279   group_base = NULL;
2280   if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
2281                                &group_base, &group_count, LDAP_SCOPE_SUBTREE) != 0))
2282     return(1);
2283   if (group_count != 1)
2284     {
2285       linklist_free(group_base);
2286       com_err(whoami, 0, "Unable to process group security template: %s - security not set", GroupSecurityTemplate);
2287       return(1);
2288     }
2289   strcpy(TemplateDn, group_base->dn);
2290   strcpy(TemplateSamName, group_base->value);
2291   linklist_free(group_base);
2292   group_base = NULL;
2293   group_count = 0;
2294
2295   sprintf(filter_exp, "(sAMAccountName=%s)", TemplateSamName);
2296   rc = ldap_search_ext_s(ldap_handle,
2297                          TemplateDn,
2298                          LDAP_SCOPE_SUBTREE,
2299                          filter_exp,
2300                          NULL,
2301                          0,
2302                          apsServerControls,
2303                          NULL,
2304                          NULL,
2305                          0,
2306                          &psMsg);
2307
2308   if ((psMsg = ldap_first_entry(ldap_handle, psMsg)) == NULL)
2309     {
2310       com_err(whoami, 0, "Unable to find group security template: %s - security not set", GroupSecurityTemplate);
2311       return(1);
2312     }
2313   ppsValues = ldap_get_values_len(ldap_handle, psMsg, "ntSecurityDescriptor");
2314   if (ppsValues == NULL)
2315     {
2316       com_err(whoami, 0, "Unable to find group security descriptor for group %s - security not set", GroupSecurityTemplate);
2317       return(1);
2318     }
2319
2320   if (AceSidCount != 0)
2321     {
2322       for (nVal = 0; ppsValues[nVal] != NULL; nVal++)
2323         {
2324           for (i = 0; i < (int)(ppsValues[nVal]->bv_len - UserTemplateSidCount); i++)
2325             {
2326               if (!memcmp(&ppsValues[nVal]->bv_val[i], UserTemplateSid, UserTemplateSidCount))
2327                 {
2328                   memcpy(&ppsValues[nVal]->bv_val[i], AceSid, AceSidCount);
2329                   break;
2330                 }
2331             }
2332         }
2333     }
2334
2335   n = 0;
2336   ADD_ATTR("ntSecurityDescriptor", (char **)ppsValues, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES);
2337   mods[n] = NULL;
2338
2339   rc = ldap_modify_s(ldap_handle, TargetDn, mods);
2340   for (i = 0; i < n; i++)
2341     free(mods[i]);
2342   ldap_value_free_len(ppsValues);
2343   ldap_msgfree(psMsg);
2344   if (rc != LDAP_SUCCESS)
2345     {
2346       com_err(whoami, 0, "Unable to set security settings for group %s : %s",
2347               TargetGroupName, ldap_err2string(rc));
2348       if (AceSidCount != 0)
2349         {
2350           com_err(whoami, 0, "Trying to set security for group %s without admin.",
2351                   TargetGroupName);
2352           if (rc = ProcessGroupSecurity(ldap_handle, dn_path, TargetGroupName, 
2353                                         HiddenGroup, "", ""))
2354             {
2355               com_err(whoami, 0, "Unable to set security for group %s.",
2356                       TargetGroupName);
2357               return(rc);
2358             }
2359         }
2360       return(rc);
2361     }
2362   return(rc);
2363 }
2364
2365 int group_delete(LDAP *ldap_handle, char *dn_path, char *group_name, 
2366                  char *group_membership, char *MoiraId)
2367 {
2368   LK_ENTRY  *group_base;
2369   char      temp[512];
2370   char      filter[128];
2371   int       group_count;
2372   int       rc;
2373
2374   if (!check_string(group_name))
2375     {
2376       com_err(whoami, 0, "Unable to process invalid LDAP list name %s", group_name);
2377       return(AD_INVALID_NAME);
2378     }
2379
2380   memset(filter, '\0', sizeof(filter));
2381   group_count = 0;
2382   group_base = NULL;
2383   sprintf(temp, "%s,%s", group_ou_root, dn_path);
2384   if (rc = ad_get_group(ldap_handle, temp, group_name, 
2385                         group_membership, MoiraId, 
2386                         "distinguishedName", &group_base, 
2387                         &group_count, filter))
2388     return(rc);
2389
2390   if (group_count == 1)
2391     {
2392       if ((rc = ldap_delete_s(ldap_handle, group_base->value)) != LDAP_SUCCESS)
2393         {
2394           linklist_free(group_base);
2395           com_err(whoami, 0, "Unable to delete list %s from AD : %s",
2396                   group_name, ldap_err2string(rc));
2397           return(rc);
2398         }
2399       linklist_free(group_base);
2400     }
2401   else
2402     {
2403       linklist_free(group_base);
2404       com_err(whoami, 0, "Unable to find list %s in AD.", group_name);
2405       return(AD_NO_GROUPS_FOUND);
2406     }
2407
2408   return(0);
2409 }
2410
2411 int BEREncodeSecurityBits(ULONG uBits, char *pBuffer)
2412 {
2413     *pBuffer++ = 0x30;
2414     *pBuffer++ = 0x03;
2415     *pBuffer++ = 0x02;
2416     *pBuffer++ = 0x00;
2417     return(N_SD_BER_BYTES);
2418 }
2419
2420 int process_lists(int ac, char **av, void *ptr)
2421 {
2422   int   rc;
2423   int   security_flag;
2424   char  group_ou[256];
2425   char  group_membership[2];
2426   char  **call_args;
2427
2428   call_args = ptr;
2429
2430   security_flag = 0;
2431   memset(group_ou, '\0', sizeof(group_ou));
2432   memset(group_membership, '\0', sizeof(group_membership));
2433   get_group_membership(group_membership, group_ou, &security_flag, av);
2434   rc = member_add((LDAP *)call_args[0], (char *)call_args[1], av[L_NAME],
2435                   group_ou, group_membership, call_args[2], 
2436                   (char *)call_args[3], "");
2437   return(0);
2438 }
2439
2440 int member_list_build(int ac, char **av, void *ptr)
2441 {
2442   LK_ENTRY  *linklist;
2443   char      temp[1024];
2444   char      **call_args;
2445
2446   call_args = ptr;
2447
2448   strcpy(temp, av[ACE_NAME]);
2449   if (!check_string(temp))
2450     return(0);
2451   if (!strcmp(av[ACE_TYPE], "USER"))
2452     {
2453       if (!((int)call_args[3] & MOIRA_USERS))
2454         return(0);
2455     }
2456   else if (!strcmp(av[ACE_TYPE], "STRING"))
2457     {
2458       if (!((int)call_args[3] & MOIRA_STRINGS))
2459         return(0);
2460       if (contact_create((LDAP *)call_args[0], call_args[1], temp, contact_ou))
2461         return(0);
2462     }
2463   else if (!strcmp(av[ACE_TYPE], "LIST"))
2464     {
2465       if (!((int)call_args[3] & MOIRA_LISTS))
2466         return(0);
2467     }
2468   else if (!strcmp(av[ACE_TYPE], "KERBEROS"))
2469     {
2470       if (!((int)call_args[3] & MOIRA_KERBEROS))
2471         return(0);
2472       if (contact_create((LDAP *)call_args[0], call_args[1], temp, kerberos_ou))
2473         return(0);
2474     }
2475   else
2476     return(0);
2477
2478   linklist = member_base;
2479   while (linklist)
2480     {
2481     if (!strcasecmp(temp, linklist->member))
2482       return(0);
2483     linklist = linklist->next;
2484     }
2485   linklist = calloc(1, sizeof(LK_ENTRY));
2486   linklist->op = 1;
2487   linklist->dn = NULL;
2488   linklist->list = calloc(1, strlen(call_args[2]) + 1);
2489   strcpy(linklist->list, call_args[2]);
2490   linklist->type = calloc(1, strlen(av[ACE_TYPE]) + 1);
2491   strcpy(linklist->type, av[ACE_TYPE]);
2492   linklist->member = calloc(1, strlen(temp) + 1);
2493   strcpy(linklist->member, temp);
2494   linklist->next = member_base;
2495   member_base = linklist;
2496   return(0);
2497 }
2498
2499 int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name, 
2500                   char *group_ou, char *group_membership, char *user_name,
2501                   char *UserOu, char *MoiraId)
2502 {
2503   char        distinguished_name[1024];
2504   char        *modvalues[2];
2505   char        temp[256];
2506   char        filter[128];
2507   int         group_count;
2508   int         i;
2509   int         n;
2510   LDAPMod     *mods[20];
2511   LK_ENTRY    *group_base;
2512   ULONG       rc;
2513
2514   if (!check_string(group_name))
2515     return(AD_INVALID_NAME);
2516
2517   memset(filter, '\0', sizeof(filter));
2518   group_base = NULL;
2519   group_count = 0;
2520   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
2521                         group_membership, MoiraId, 
2522                         "distinguishedName", &group_base, 
2523                         &group_count, filter))
2524     return(rc);
2525
2526   if (group_count != 1)
2527     {
2528       com_err(whoami, 0, "Unable to find list %s in AD",
2529               group_name);
2530       linklist_free(group_base);
2531       group_base = NULL;
2532       group_count = 0;
2533       goto cleanup;
2534     }
2535   strcpy(distinguished_name, group_base->value);
2536   linklist_free(group_base);
2537   group_base = NULL;
2538   group_count = 0;
2539
2540   sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
2541   modvalues[0] = temp;
2542   modvalues[1] = NULL;
2543
2544   n = 0;
2545   ADD_ATTR("member", modvalues, LDAP_MOD_DELETE);
2546   mods[n] = NULL;
2547   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2548   for (i = 0; i < n; i++)
2549     free(mods[i]);
2550   if (rc == LDAP_UNWILLING_TO_PERFORM)
2551     rc = LDAP_SUCCESS;
2552   if (rc != LDAP_SUCCESS)
2553     {
2554       com_err(whoami, 0, "Unable to modify list %s members : %s",
2555               group_name, ldap_err2string(rc));
2556       goto cleanup;
2557     }
2558
2559 cleanup:
2560   return(rc);
2561 }
2562
2563 int member_add(LDAP *ldap_handle, char *dn_path, char *group_name, 
2564                char *group_ou, char *group_membership, char *user_name, 
2565                char *UserOu, char *MoiraId)
2566 {
2567   char        distinguished_name[1024];
2568   char        *modvalues[2];
2569   char        temp[256];
2570   char        filter[128];
2571   int         group_count;
2572   int         n;
2573   int         i;
2574   LDAPMod     *mods[20];
2575   LK_ENTRY    *group_base;
2576   ULONG       rc;
2577
2578   if (!check_string(group_name))
2579     return(AD_INVALID_NAME);
2580
2581   rc = 0;
2582   memset(filter, '\0', sizeof(filter));
2583   group_base = NULL;
2584   group_count = 0;
2585   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
2586                         group_membership, MoiraId, 
2587                         "distinguishedName", &group_base, 
2588                         &group_count, filter))
2589     return(rc);
2590
2591   if (group_count != 1)
2592     {
2593       linklist_free(group_base);
2594       group_base = NULL;
2595       group_count = 0;
2596       com_err(whoami, 0, "Unable to find list %s in AD",
2597               group_name);
2598       return(AD_MULTIPLE_GROUPS_FOUND);
2599     }
2600
2601   strcpy(distinguished_name, group_base->value);
2602   linklist_free(group_base);
2603   group_base = NULL;
2604   group_count = 0;
2605
2606   sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
2607   modvalues[0] = temp;
2608   modvalues[1] = NULL;
2609
2610   n = 0;
2611   ADD_ATTR("member", modvalues, LDAP_MOD_ADD);
2612   mods[n] = NULL;
2613   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2614   if (rc == LDAP_ALREADY_EXISTS)
2615     rc = LDAP_SUCCESS;
2616   if ((!strcmp(UserOu, contact_ou)) || (!strcmp(UserOu, kerberos_ou)))
2617     {
2618       if (rc == LDAP_UNWILLING_TO_PERFORM)
2619         rc = LDAP_SUCCESS;
2620     }
2621   for (i = 0; i < n; i++)
2622     free(mods[i]);
2623   if (rc != LDAP_SUCCESS)
2624     {
2625       com_err(whoami, 0, "Unable to add %s to list %s as a member : %s",
2626               user_name, group_name, ldap_err2string(rc));
2627     }
2628
2629   return(rc);
2630 }
2631
2632 int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou)
2633 {
2634   LDAPMod *mods[20];
2635   char new_dn[256];
2636   char cn_user_name[256];
2637   char contact_name[256];
2638   char *email_v[] = {NULL, NULL};
2639   char *cn_v[] = {NULL, NULL};
2640   char *contact_v[] = {NULL, NULL};
2641   char *objectClass_v[] = {"top", "person", 
2642                            "organizationalPerson", 
2643                            "contact", NULL};
2644   char *name_v[] = {NULL, NULL};
2645   char *desc_v[] = {NULL, NULL};
2646   int  n;
2647   int  rc;
2648   int  i;
2649
2650   if (!check_string(user))
2651     {
2652       com_err(whoami, 0, "Unable to process invalid LDAP name %s", user);
2653       return(AD_INVALID_NAME);
2654     }
2655   strcpy(contact_name, user);
2656   sprintf(cn_user_name,"CN=%s,%s,%s", contact_name, group_ou, bind_path);
2657   cn_v[0] = cn_user_name;
2658   contact_v[0] = contact_name;
2659   name_v[0] = user;
2660   desc_v[0] = "Auto account created by Moira";
2661   email_v[0] = user;
2662
2663   strcpy(new_dn, cn_user_name);
2664   n = 0;
2665   ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
2666   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2667   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2668   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2669   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2670   if (!strcmp(group_ou, contact_ou))
2671     {
2672       ADD_ATTR("mail", email_v, LDAP_MOD_ADD);
2673     }
2674   mods[n] = NULL;
2675
2676   rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
2677   for (i = 0; i < n; i++)
2678     free(mods[i]);
2679   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2680     {
2681       n = 0;
2682       ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
2683       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2684       ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2685       ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2686       ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2687       mods[n] = NULL;
2688       rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
2689       for (i = 0; i < n; i++)
2690         free(mods[i]);
2691     }
2692   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2693     {
2694       com_err(whoami, 0, "Unable to create contact %s : %s",
2695               user, ldap_err2string(rc));
2696       return(rc);
2697     }
2698   return(0);
2699 }
2700
2701 int user_update(LDAP *ldap_handle, char *dn_path, char *user_name,
2702                 char *Uid, char *MitId, char *MoiraId, int State,
2703                 char *WinHomeDir, char *WinProfileDir)
2704 {
2705   LDAPMod   *mods[20];
2706   LK_ENTRY  *group_base;
2707   int  group_count;
2708   char distinguished_name[512];
2709   char *mitMoiraId_v[] = {NULL, NULL};
2710   char *uid_v[] = {NULL, NULL};
2711   char *mitid_v[] = {NULL, NULL};
2712   char *homedir_v[] = {NULL, NULL};
2713   char *winProfile_v[] = {NULL, NULL};
2714   char *drives_v[] = {NULL, NULL};
2715   char *userAccountControl_v[] = {NULL, NULL};
2716   char userAccountControlStr[80];
2717   int  n;
2718   int  rc;
2719   int  i;
2720   int  OldUseSFU30;
2721   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | UF_PASSWD_CANT_CHANGE;
2722   char filter[128];
2723   char *attr_array[3];
2724   char temp[256];
2725
2726   if (!check_string(user_name))
2727     {
2728       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", user_name);
2729       return(AD_INVALID_NAME);
2730     }
2731
2732   group_count = 0;
2733   group_base = NULL;
2734
2735   if (strlen(MoiraId) != 0)
2736     {
2737       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
2738       attr_array[0] = "cn";
2739       attr_array[1] = NULL;
2740       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2741                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
2742         {
2743           com_err(whoami, 0, "Unable to process user %s : %s",
2744                   user_name, ldap_err2string(rc));
2745           return(rc);
2746         }
2747     }
2748   if (group_count != 1)
2749     {
2750       linklist_free(group_base);
2751       group_base = NULL;
2752       group_count = 0;
2753       sprintf(filter, "(sAMAccountName=%s)", user_name);
2754       attr_array[0] = "cn";
2755       attr_array[1] = NULL;
2756       sprintf(temp, "%s,%s", user_ou, dn_path);
2757       if ((rc = linklist_build(ldap_handle, temp, filter, attr_array, 
2758                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
2759         {
2760           com_err(whoami, 0, "Unable to process user %s : %s",
2761                   user_name, ldap_err2string(rc));
2762           return(rc);
2763         }
2764     }
2765
2766   if (group_count != 1)
2767     {
2768       com_err(whoami, 0, "Unable to find user %s in AD",
2769               user_name);
2770       linklist_free(group_base);
2771       return(AD_NO_USER_FOUND);
2772     }
2773   strcpy(distinguished_name, group_base->dn);
2774
2775   linklist_free(group_base);
2776   group_count = 0;
2777
2778   if ((strlen(MitId) != 0) && (MitId[0] == '9'))
2779     rc = attribute_update(ldap_handle, distinguished_name, MitId, "employeeID", user_name);
2780   else
2781     rc = attribute_update(ldap_handle, distinguished_name, "none", "employeeID", user_name);
2782   rc = attribute_update(ldap_handle, distinguished_name, Uid, "uid", user_name);
2783   rc = attribute_update(ldap_handle, distinguished_name, MoiraId, "mitMoiraId", user_name);
2784
2785   n = 0;
2786   uid_v[0] = Uid;
2787   if (!UseSFU30)
2788     {
2789       ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
2790     }
2791   else
2792     {
2793       ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_REPLACE);
2794     }
2795
2796
2797   if ((State != US_NO_PASSWD) && (State != US_REGISTERED))
2798     userAccountControl |= UF_ACCOUNTDISABLE;
2799   sprintf(userAccountControlStr, "%ld", userAccountControl);
2800   userAccountControl_v[0] = userAccountControlStr;
2801   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_REPLACE);
2802
2803   n = SetHomeDirectory(ldap_handle, user_name, distinguished_name, WinHomeDir, 
2804                        WinProfileDir, homedir_v, winProfile_v,
2805                        drives_v, mods, LDAP_MOD_REPLACE, n);
2806
2807   mods[n] = NULL;
2808   if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) != LDAP_SUCCESS)
2809     {
2810         OldUseSFU30 = UseSFU30;
2811         SwitchSFU(mods, &UseSFU30, n);
2812         if (OldUseSFU30 != UseSFU30)
2813             rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2814         if (rc)
2815         {
2816             com_err(whoami, 0, "Unable to modify user data for %s : %s",
2817                 user_name, ldap_err2string(rc));
2818         }
2819     }
2820   for (i = 0; i < n; i++)
2821     free(mods[i]);
2822   return(rc);
2823 }
2824
2825 int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name, 
2826                 char *user_name)
2827 {
2828   LDAPMod *mods[20];
2829   char new_dn[256];
2830   char old_dn[256];
2831   char upn[256];
2832   char temp[128];
2833   char *userPrincipalName_v[] = {NULL, NULL};
2834   char *altSecurityIdentities_v[] = {NULL, NULL};
2835   char *name_v[] = {NULL, NULL};
2836   char *samAccountName_v[] = {NULL, NULL};
2837   int  n;
2838   int  rc;
2839   int  i;
2840
2841   if (!check_string(before_user_name))
2842     {
2843       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", before_user_name);
2844       return(AD_INVALID_NAME);
2845     }
2846   if (!check_string(user_name))
2847     {
2848       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", user_name);
2849       return(AD_INVALID_NAME);
2850     }
2851
2852   strcpy(user_name, user_name);
2853   sprintf(old_dn, "cn=%s,%s,%s", before_user_name, user_ou, dn_path);
2854   sprintf(new_dn, "cn=%s", user_name);
2855   if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, NULL, TRUE, 
2856                            NULL, NULL)) != LDAP_SUCCESS)
2857     {
2858       com_err(whoami, 0, "Unable to rename user from %s to %s : %s",
2859               before_user_name, user_name, ldap_err2string(rc));
2860       return(rc);
2861     }
2862
2863   name_v[0] = user_name;
2864   sprintf(upn, "%s@%s", user_name, ldap_domain);
2865   userPrincipalName_v[0] = upn;
2866   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
2867   altSecurityIdentities_v[0] = temp;
2868   samAccountName_v[0] = user_name;
2869
2870   n = 0;
2871   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_REPLACE);
2872   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_REPLACE);
2873   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
2874   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_REPLACE);
2875   mods[n] = NULL;
2876   sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, dn_path);
2877   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
2878     {
2879       com_err(whoami, 0, "Unable to modify user data for %s after renaming : %s",
2880               user_name, ldap_err2string(rc));
2881     }
2882   for (i = 0; i < n; i++)
2883     free(mods[i]);
2884   return(rc);
2885 }
2886
2887 int user_create(int ac, char **av, void *ptr)
2888 {
2889   LDAPMod *mods[20];
2890   char new_dn[256];
2891   char user_name[256];
2892   char sam_name[256];
2893   char upn[256];
2894   char *cn_v[] = {NULL, NULL};
2895   char *objectClass_v[] = {"top", "person", 
2896                            "organizationalPerson", 
2897                            "user", NULL};
2898
2899   char *samAccountName_v[] = {NULL, NULL};
2900   char *altSecurityIdentities_v[] = {NULL, NULL};
2901   char *mitMoiraId_v[] = {NULL, NULL};
2902   char *name_v[] = {NULL, NULL};
2903   char *desc_v[] = {NULL, NULL};
2904   char *userPrincipalName_v[] = {NULL, NULL};
2905   char *userAccountControl_v[] = {NULL, NULL};
2906   char *uid_v[] = {NULL, NULL};
2907   char *mitid_v[] = {NULL, NULL};
2908   char *homedir_v[] = {NULL, NULL};
2909   char *winProfile_v[] = {NULL, NULL};
2910   char *drives_v[] = {NULL, NULL};
2911   char userAccountControlStr[80];
2912   char temp[128];
2913   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | UF_PASSWD_CANT_CHANGE;
2914   int  n;
2915   int  rc;
2916   int  i;
2917   int  OldUseSFU30;
2918   char **call_args;
2919   char WinHomeDir[1024];
2920   char WinProfileDir[1024];
2921
2922   call_args = ptr;
2923
2924   if (!check_string(av[U_NAME]))
2925     {
2926       callback_rc = AD_INVALID_NAME;
2927       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", av[U_NAME]);
2928       return(AD_INVALID_NAME);
2929     }
2930
2931   memset(WinHomeDir, '\0', sizeof(WinHomeDir));
2932   memset(WinProfileDir, '\0', sizeof(WinProfileDir));
2933   strcpy(WinHomeDir, av[U_WINHOMEDIR]);
2934   strcpy(WinProfileDir, av[U_WINPROFILEDIR]);
2935   strcpy(user_name, av[U_NAME]);
2936   sprintf(upn, "%s@%s", user_name, ldap_domain);
2937   sprintf(sam_name, "%s", av[U_NAME]);
2938   samAccountName_v[0] = sam_name;
2939   if ((atoi(av[U_STATE]) != US_NO_PASSWD) && (atoi(av[U_STATE]) != US_REGISTERED))
2940     userAccountControl |= UF_ACCOUNTDISABLE;
2941   sprintf(userAccountControlStr, "%ld", userAccountControl);
2942   userAccountControl_v[0] = userAccountControlStr;
2943   userPrincipalName_v[0] = upn;
2944
2945   cn_v[0] = user_name;
2946   name_v[0] = user_name;
2947   desc_v[0] = "Auto account created by Moira";
2948   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
2949   altSecurityIdentities_v[0] = temp;    
2950   sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, call_args[1]);
2951
2952   n = 0;
2953   ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
2954   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2955   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
2956   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_ADD);
2957   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_ADD);
2958   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2959   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2960   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2961   if (strlen(call_args[2]) != 0)    
2962     {
2963       mitMoiraId_v[0] = call_args[2];
2964       ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
2965     }
2966   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_ADD);
2967   if (strlen(av[U_UID]) != 0)
2968     {
2969       uid_v[0] = av[U_UID];
2970       ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
2971       if (!UseSFU30)
2972         {
2973           ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
2974         }
2975       else
2976         {
2977           ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_ADD);
2978         }
2979     }
2980   if ((strlen(av[U_MITID]) != 0) && (av[U_MITID][0] == '9'))
2981       mitid_v[0] = av[U_MITID];
2982   else
2983       mitid_v[0] = "none";
2984   ADD_ATTR("employeeID", mitid_v, LDAP_MOD_ADD);
2985
2986   n = SetHomeDirectory((LDAP *)call_args[0], user_name, new_dn, WinHomeDir, 
2987                        WinProfileDir, homedir_v, winProfile_v,
2988                        drives_v, mods, LDAP_MOD_ADD, n);
2989
2990   mods[n] = NULL;
2991
2992   rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
2993   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2994   {
2995       OldUseSFU30 = UseSFU30;
2996       SwitchSFU(mods, &UseSFU30, n);
2997       if (OldUseSFU30 != UseSFU30)
2998           rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
2999   }
3000
3001   for (i = 0; i < n; i++)
3002     free(mods[i]);
3003   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
3004     {
3005       com_err(whoami, 0, "Unable to create user %s : %s",
3006               user_name, ldap_err2string(rc));
3007       callback_rc = rc;
3008       return(rc);
3009     }
3010   if (rc == LDAP_SUCCESS)
3011     {
3012       if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
3013         {
3014           ad_kdc_disconnect();
3015           tickets_get_k5();
3016           if (!ad_server_connect(default_server, ldap_domain))
3017             {
3018               com_err(whoami, 0, "Unable to set password for user %s : %s",
3019                       user_name, "cannot get changepw ticket from windows domain");
3020             }
3021           else
3022             {
3023               if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
3024                 {
3025                   com_err(whoami, 0, "Unable to set password for user %s : %ld",
3026                           user_name, rc);
3027                 }
3028             }
3029         }
3030     }
3031   return(0);
3032 }
3033
3034 int user_change_status(LDAP *ldap_handle, char *dn_path, 
3035                        char *user_name, char *MoiraId,
3036                        int operation)
3037 {
3038   char      filter[128];
3039   char      *attr_array[3];
3040   char      temp[256];
3041   char      distinguished_name[1024];
3042   char      **modvalues;
3043   char      *mitMoiraId_v[] = {NULL, NULL};
3044   LDAPMod   *mods[20];
3045   LK_ENTRY  *group_base;
3046   int       group_count;
3047   int       rc;
3048   int       i;
3049   int       n;
3050   ULONG     ulongValue;
3051
3052   if (!check_string(user_name))
3053     {
3054       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", user_name);
3055       return(AD_INVALID_NAME);
3056     }
3057
3058   group_count = 0;
3059   group_base = NULL;
3060
3061   if (strlen(MoiraId) != 0)
3062     {
3063       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
3064       attr_array[0] = "UserAccountControl";
3065       attr_array[1] = NULL;
3066       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3067                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3068         {
3069           com_err(whoami, 0, "Unable to process user %s : %s",
3070                   user_name, ldap_err2string(rc));
3071           return(rc);
3072         }
3073     }
3074   if (group_count != 1)
3075     {
3076       linklist_free(group_base);
3077       group_count = 0;
3078       group_base = NULL;
3079       sprintf(filter, "(sAMAccountName=%s)", user_name);
3080       attr_array[0] = "UserAccountControl";
3081       attr_array[1] = NULL;
3082       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3083                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3084         {
3085           com_err(whoami, 0, "Unable to process user %s : %s",
3086                   user_name, ldap_err2string(rc));
3087           return(rc);
3088         }
3089     }
3090
3091   if (group_count != 1)
3092     {
3093       linklist_free(group_base);
3094       com_err(whoami, 0, "Unable to find user %s in AD",
3095               user_name);
3096       return(LDAP_NO_SUCH_OBJECT);
3097     }
3098
3099   strcpy(distinguished_name, group_base->dn);
3100   ulongValue = atoi((*group_base).value);
3101   if (operation == MEMBER_DEACTIVATE)
3102     ulongValue |= UF_ACCOUNTDISABLE;
3103   else    
3104     ulongValue &= ~UF_ACCOUNTDISABLE;
3105   sprintf(temp, "%ld", ulongValue);
3106   if ((rc = construct_newvalues(group_base, group_count, (*group_base).value, 
3107                                 temp, &modvalues, REPLACE)) == 1)
3108     goto cleanup;
3109   linklist_free(group_base);
3110   group_base = NULL;
3111   group_count = 0;
3112   n = 0;
3113   ADD_ATTR("UserAccountControl", modvalues, LDAP_MOD_REPLACE);
3114   if (strlen(MoiraId) != 0)
3115     {
3116     mitMoiraId_v[0] = MoiraId;
3117     ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
3118     }
3119   mods[n] = NULL;
3120   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
3121   for (i = 0; i < n; i++)
3122     free(mods[i]);
3123   free_values(modvalues);
3124   if (rc != LDAP_SUCCESS)
3125     {
3126       com_err(whoami, 0, "Unable to change status of user %s : %s",
3127               user_name, ldap_err2string(rc));
3128     }
3129 cleanup:
3130   return(rc);
3131 }
3132
3133 int user_delete(LDAP *ldap_handle, char *dn_path, 
3134                 char *u_name, char *MoiraId)
3135 {
3136   char      filter[128];
3137   char      *attr_array[3];
3138   char      distinguished_name[1024];
3139   char      user_name[512];
3140   LK_ENTRY  *group_base;
3141   int       group_count;
3142   int       rc;
3143
3144   if (!check_string(u_name))
3145     return(AD_INVALID_NAME);
3146
3147   strcpy(user_name, u_name);
3148   group_count = 0;
3149   group_base = NULL;
3150
3151   if (strlen(MoiraId) != 0)
3152     {
3153       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
3154       attr_array[0] = "name";
3155       attr_array[1] = NULL;
3156       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3157                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3158         {
3159           com_err(whoami, 0, "Unable to process user %s : %s",
3160                   user_name, ldap_err2string(rc));
3161           goto cleanup;
3162         }
3163     }
3164   if (group_count != 1)
3165     {
3166       linklist_free(group_base);
3167       group_count = 0;
3168       group_base = NULL;
3169       sprintf(filter, "(sAMAccountName=%s)", user_name);
3170       attr_array[0] = "name";
3171       attr_array[1] = NULL;
3172       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3173                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3174         {
3175           com_err(whoami, 0, "Unable to process user %s : %s",
3176                   user_name, ldap_err2string(rc));
3177           goto cleanup;
3178         }
3179     }
3180
3181   if (group_count != 1)
3182     {
3183       com_err(whoami, 0, "Unable to find user %s in AD",
3184               user_name);
3185       goto cleanup;
3186     }
3187
3188   strcpy(distinguished_name, group_base->dn);
3189   if (rc = ldap_delete_s(ldap_handle, distinguished_name))
3190     {
3191       com_err(whoami, 0, "Unable to process user %s : %s",
3192               user_name, ldap_err2string(rc));
3193     }
3194
3195 cleanup:
3196   linklist_free(group_base);
3197   return(0);
3198 }
3199
3200 void linklist_free(LK_ENTRY *linklist_base)
3201 {
3202   LK_ENTRY *linklist_previous;
3203
3204   while (linklist_base != NULL)
3205     {
3206       if (linklist_base->dn != NULL)
3207         free(linklist_base->dn);
3208       if (linklist_base->attribute != NULL)
3209         free(linklist_base->attribute);
3210       if (linklist_base->value != NULL)
3211         free(linklist_base->value);
3212       if (linklist_base->member != NULL)
3213         free(linklist_base->member);
3214       if (linklist_base->type != NULL)
3215         free(linklist_base->type);
3216       if (linklist_base->list != NULL)
3217         free(linklist_base->list);
3218       linklist_previous = linklist_base;
3219       linklist_base = linklist_previous->next;
3220       free(linklist_previous);
3221     }
3222 }
3223
3224 void free_values(char **modvalues)
3225 {
3226   int i;
3227
3228   i = 0;
3229   if (modvalues != NULL)
3230     {
3231     while (modvalues[i] != NULL)
3232       {
3233         free(modvalues[i]);
3234         modvalues[i] = NULL;
3235         ++i;
3236       }
3237     free(modvalues);
3238   }
3239 }
3240
3241 static int illegalchars[] = {
3242   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
3243   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
3244   1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */
3245   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
3246   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
3247   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
3248   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
3249   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
3250   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3251   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3252   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3253   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3254   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3255   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3256   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3257   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3258 };
3259
3260 int check_string(char *s)
3261 {
3262   char  character;
3263
3264   for (; *s; s++)
3265     {
3266       character = *s;
3267       if (isupper(character))
3268         character = tolower(character);
3269       if (illegalchars[(unsigned) character])
3270         return 0;
3271     }
3272   return 1;
3273 }
3274
3275 int check_container_name(char *s)
3276 {
3277   char  character;
3278
3279   for (; *s; s++)
3280     {
3281       character = *s;
3282       if (isupper(character))
3283         character = tolower(character);
3284
3285           if (character == ' ')
3286                   continue;
3287       if (illegalchars[(unsigned) character])
3288         return 0;
3289     }
3290   return 1;
3291 }
3292
3293 int mr_connect_cl(char *server, char *client, int version, int auth)
3294 {
3295   int   status;
3296   char  *motd;
3297   char  temp[128];
3298
3299   status = mr_connect(server);
3300   if (status)
3301     {
3302       com_err(whoami, status, "while connecting to Moira");
3303       return status;
3304     }
3305
3306   status = mr_motd(&motd);
3307   if (status)
3308     {
3309       mr_disconnect();
3310       com_err(whoami, status, "while checking server status");
3311       return status;
3312     }
3313   if (motd)
3314     {
3315       sprintf(temp, "The Moira server is currently unavailable: %s", motd);
3316       com_err(whoami, status, temp);
3317       mr_disconnect();
3318       return status;
3319     }
3320
3321   status = mr_version(version);
3322   if (status)
3323     {
3324       if (status == MR_UNKNOWN_PROC)
3325         {
3326           if (version > 2)
3327             status = MR_VERSION_HIGH;
3328           else
3329             status = MR_SUCCESS;
3330         }
3331
3332       if (status == MR_VERSION_HIGH)
3333         {
3334           com_err(whoami, 0, "Warning: This client is running newer code than the server.");
3335                   com_err(whoami, 0, "Some operations may not work.");
3336         }
3337       else if (status && status != MR_VERSION_LOW)
3338         {
3339           com_err(whoami, status, "while setting query version number.");
3340           mr_disconnect();
3341           return status;
3342         }
3343     }
3344
3345   if (auth)
3346     {
3347       status = mr_auth(client);
3348       if (status)
3349         {
3350           com_err(whoami, status, "while authenticating to Moira.");
3351           mr_disconnect();
3352           return status;
3353         }
3354     }
3355
3356   return MR_SUCCESS;
3357 }
3358
3359 void AfsToWinAfs(char* path, char* winPath)
3360 {
3361     char* pathPtr;
3362     char* winPathPtr;
3363     strcpy(winPath, WINAFS);
3364     pathPtr = path + strlen(AFS);
3365     winPathPtr = winPath + strlen(WINAFS);
3366
3367     while (*pathPtr)
3368     {
3369         if (*pathPtr == '/')
3370           *winPathPtr = '\\';
3371         else
3372           *winPathPtr = *pathPtr;
3373
3374         pathPtr++;
3375         winPathPtr++;
3376     }
3377 }
3378
3379 int GetAceInfo(int ac, char **av, void *ptr)
3380 {
3381   char **call_args;
3382   int   security_flag;
3383
3384   call_args = ptr;
3385
3386   strcpy(call_args[0], av[L_ACE_TYPE]);
3387   strcpy(call_args[1], av[L_ACE_NAME]);
3388   security_flag = 0;
3389   get_group_membership(call_args[2], call_args[3], &security_flag, av);
3390   return(LDAP_SUCCESS);
3391
3392 }
3393
3394 int checkADname(LDAP *ldap_handle, char *dn_path, char *Name)
3395 {
3396   char filter[128];
3397   char *attr_array[3];
3398   int  group_count;
3399   int  rc;
3400   LK_ENTRY  *group_base;
3401
3402   group_count = 0;
3403   group_base = NULL;
3404
3405   sprintf(filter, "(sAMAccountName=%s)", Name);
3406   attr_array[0] = "sAMAccountName";
3407   attr_array[1] = NULL;
3408   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3409                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3410     {
3411       com_err(whoami, 0, "Unable to process ACE name %s : %s",
3412               Name, ldap_err2string(rc));
3413       return(1);
3414     }
3415
3416   linklist_free(group_base);
3417   group_base = NULL;
3418   if (group_count == 0)
3419     return(0);
3420   return(1);
3421 }
3422
3423 #define MAX_ACE 7
3424
3425 int ProcessAce(LDAP *ldap_handle, char *dn_path, char *Name, char *Type, int UpdateGroup, int *ProcessGroup)
3426 {
3427   char  *av[2];
3428   char  GroupName[256];
3429   char  *call_args[7];
3430   int   rc;
3431   char  *AceInfo[4];
3432   char  AceType[32];
3433   char  AceName[128];
3434   char  AceMembership[2];
3435   char  AceOu[256];
3436   char  temp[128];
3437
3438   strcpy(GroupName, Name);
3439
3440   if (strcasecmp(Type, "LIST"))
3441     return(1);
3442   while (1)
3443     {
3444       av[0] = GroupName;
3445       AceInfo[0] = AceType;
3446       AceInfo[1] = AceName;
3447       AceInfo[2] = AceMembership;
3448       AceInfo[3] = AceOu;
3449       memset(AceType, '\0', sizeof(AceType));
3450       memset(AceName, '\0', sizeof(AceName));
3451       memset(AceMembership, '\0', sizeof(AceMembership));
3452       memset(AceOu, '\0', sizeof(AceOu));
3453       callback_rc = 0;
3454       if (rc = mr_query("get_list_info", 1, av, GetAceInfo, AceInfo))
3455         {
3456           com_err(whoami, 0, "Unable to get ACE info for list %s : %s", GroupName, error_message(rc));
3457           return(1);
3458         }
3459       if (callback_rc)
3460         {
3461           com_err(whoami, 0, "Unable to get ACE info for list %s", GroupName);
3462           return(1);
3463         }
3464       if ((strcasecmp(AceType, "USER")) && (strcasecmp(AceType, "LIST")))
3465         return(0);
3466       strcpy(temp, AceName);
3467       if (!strcasecmp(AceType, "LIST"))
3468         sprintf(temp, "%s_group", AceName);
3469       if (!UpdateGroup)
3470         {
3471           if (checkADname(ldap_handle, dn_path, temp))
3472             return(0);
3473           (*ProcessGroup) = 1;
3474         }
3475       if (!strcasecmp(AceInfo[0], "LIST"))
3476         {
3477           if (make_new_group(ldap_handle, dn_path, "", AceName, AceOu, AceMembership, 0, UpdateGroup))
3478             return(1);
3479         }
3480       else if (!strcasecmp(AceInfo[0], "USER"))
3481         {
3482           av[0] = AceName;
3483           call_args[0] = (char *)ldap_handle;
3484           call_args[1] = dn_path;
3485           call_args[2] = "";
3486           call_args[3] = NULL;
3487           callback_rc = 0;
3488           if (rc = mr_query("get_user_account_by_login", 1, av, user_create, call_args))
3489             {
3490               com_err(whoami, 0, "Unable to process user ACE %s for group %s.", AceName, Name);
3491               return(1);
3492             }
3493           if (callback_rc)
3494             {
3495               com_err(whoami, 0, "Unable to process user Ace %s for group %s", AceName, Name);
3496               return(1);
3497             }
3498           return(0);
3499         }
3500       else
3501         return(1);
3502       if (!strcasecmp(AceType, "LIST"))
3503         {
3504           if (!strcasecmp(GroupName, AceName))
3505             return(0);
3506         }
3507       strcpy(GroupName, AceName);
3508     }
3509   return(1);
3510 }
3511
3512 int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
3513                    char *group_name, char *group_ou, char *group_membership, 
3514                    int group_security_flag, int updateGroup)
3515 {
3516   char  *av[3];
3517   char  *call_args[7];
3518   int   rc;
3519
3520   av[0] = group_name;
3521   call_args[0] = (char *)ldap_handle;
3522   call_args[1] = dn_path;
3523   call_args[2] = group_name;
3524   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
3525   call_args[4] = (char *)updateGroup;
3526   call_args[5] = MoiraId;
3527   call_args[6] = NULL;
3528   callback_rc = 0;
3529   if (rc = mr_query("get_list_info", 1, av, group_create, call_args))
3530     {
3531       moira_disconnect();
3532       com_err(whoami, 0, "Unable to create list %s : %s", group_name, error_message(rc));
3533       return(rc);
3534     }
3535   if (callback_rc)
3536     {
3537       moira_disconnect();
3538       com_err(whoami, 0, "Unable to create list %s", group_name);
3539       return(callback_rc);
3540     }
3541
3542   return(0);
3543 }
3544
3545 int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
3546                    char *group_ou, char *group_membership, 
3547                    int group_security_flag, char *MoiraId)
3548 {
3549   char      *av[3];
3550   char      *call_args[7];
3551   char      *pUserOu;
3552   LK_ENTRY  *ptr;
3553   int       rc;
3554
3555   com_err(whoami, 0, "Populating group %s", group_name);
3556   av[0] = group_name;
3557   call_args[0] = (char *)ldap_handle;
3558   call_args[1] = dn_path;
3559   call_args[2] = group_name;
3560   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
3561   call_args[4] = NULL;
3562   member_base = NULL;
3563   if (rc = mr_query("get_end_members_of_list", 1, av,
3564                     member_list_build, call_args))
3565     {
3566       com_err(whoami, 0, "Unable to populate list %s : %s", 
3567               group_name, error_message(rc));
3568       return(3);
3569     }
3570   if (member_base != NULL)
3571     {
3572       ptr = member_base;
3573       while (ptr != NULL)
3574         {
3575           if (!strcasecmp(ptr->type, "LIST"))
3576             {
3577               ptr = ptr->next;
3578               continue;
3579             }
3580           pUserOu = user_ou;
3581           if (!strcasecmp(ptr->type, "STRING"))
3582             {
3583               if (contact_create(ldap_handle, dn_path, ptr->member, contact_ou))
3584                 return(3);
3585               pUserOu = contact_ou;
3586             }
3587           else if (!strcasecmp(ptr->type, "KERBEROS"))
3588             {
3589               if (contact_create(ldap_handle, dn_path, ptr->member, kerberos_ou))
3590                 return(3);
3591               pUserOu = kerberos_ou;
3592             }
3593           rc = member_add(ldap_handle, dn_path, group_name,
3594                           group_ou, group_membership, ptr->member, 
3595                           pUserOu, MoiraId);
3596           ptr = ptr->next;
3597         }
3598       linklist_free(member_base);
3599       member_base = NULL;
3600     }
3601   return(0);
3602 }
3603
3604 int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
3605                   char *group_name, char *group_ou, char *group_membership, 
3606                   int group_security_flag, int type)
3607 {
3608   char      before_desc[512];
3609   char      before_name[256];
3610   char      before_group_ou[256];
3611   char      before_group_membership[2];
3612   char      distinguishedName[256];
3613   char      ad_distinguishedName[256];
3614   char      filter[128];
3615   char      *attr_array[3];
3616   int       before_security_flag;
3617   int       group_count;
3618   int       rc;
3619   LK_ENTRY  *group_base;
3620   LK_ENTRY  *ptr;
3621   char      ou_both[512];
3622   char      ou_security[512];
3623   char      ou_distribution[512];
3624   char      ou_neither[512];
3625
3626   memset(ad_distinguishedName, '\0', sizeof(ad_distinguishedName));
3627   sprintf(distinguishedName, "CN=%s,%s,%s", group_name, group_ou, dn_path);
3628
3629
3630   memset(filter, '\0', sizeof(filter));
3631   group_base = NULL;
3632   group_count = 0;
3633   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
3634                         "*", MoiraId, 
3635                         "distinguishedName", &group_base, 
3636                         &group_count, filter))
3637     return(rc);
3638
3639   if (type == CHECK_GROUPS)
3640     {
3641       if (group_count == 1)
3642         {
3643           if (!strcasecmp(group_base->value, distinguishedName))
3644             {
3645               linklist_free(group_base);
3646               return(0);
3647             }
3648         }
3649       linklist_free(group_base);
3650       if (group_count == 0)
3651         return(AD_NO_GROUPS_FOUND);
3652       if (group_count == 1)
3653         return(AD_WRONG_GROUP_DN_FOUND);
3654       return(AD_MULTIPLE_GROUPS_FOUND);
3655     }
3656   if (group_count == 0)
3657     {
3658       return(AD_NO_GROUPS_FOUND);
3659     }
3660   if (group_count > 1)
3661     {
3662       ptr = group_base;
3663       while (ptr != NULL)
3664         {
3665           if (!strcasecmp(distinguishedName, ptr->value))
3666             break;
3667           ptr = ptr->next;
3668         }
3669       if (ptr == NULL)
3670         {
3671           com_err(whoami, 0, "%d groups with moira id = %s", group_count, MoiraId);
3672           ptr = group_base;
3673           while (ptr != NULL)
3674             {
3675               com_err(whoami, 0, "%s with moira id = %s", ptr->value, MoiraId);
3676               ptr = ptr->next;
3677             }
3678           linklist_free(group_base);
3679           return(AD_MULTIPLE_GROUPS_FOUND);
3680         }
3681       ptr = group_base;
3682       while (ptr != NULL)
3683         {
3684           if (strcasecmp(distinguishedName, ptr->value))
3685             rc = ldap_delete_s(ldap_handle, ptr->value);
3686           ptr = ptr->next;
3687         }
3688       linklist_free(group_base);
3689       memset(filter, '\0', sizeof(filter));
3690       group_base = NULL;
3691       group_count = 0;
3692       if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
3693                             "*", MoiraId, 
3694                             "distinguishedName", &group_base, 
3695                             &group_count, filter))
3696         return(rc);
3697       if (group_count == 0)
3698         return(AD_NO_GROUPS_FOUND);
3699       if (group_count > 1)
3700         return(AD_MULTIPLE_GROUPS_FOUND);
3701     }
3702
3703   strcpy(ad_distinguishedName, group_base->value);
3704   linklist_free(group_base);
3705   group_base = NULL;
3706   group_count = 0;
3707
3708   attr_array[0] = "sAMAccountName";
3709   attr_array[1] = NULL;
3710   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3711                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3712     {
3713       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
3714                MoiraId, ldap_err2string(rc));
3715       return(rc);
3716     }
3717   sprintf(filter, "(sAMAccountName=%s)", group_base->value);
3718
3719   if (!strcasecmp(ad_distinguishedName, distinguishedName))
3720     {
3721       linklist_free(group_base);
3722       group_base = NULL;
3723       group_count = 0;
3724       return(0);
3725     }
3726   linklist_free(group_base);
3727   group_base = NULL;
3728   group_count = 0;
3729   memset(ou_both, '\0', sizeof(ou_both));
3730   memset(ou_security, '\0', sizeof(ou_security));
3731   memset(ou_distribution, '\0', sizeof(ou_distribution));
3732   memset(ou_neither, '\0', sizeof(ou_neither));
3733   memset(before_name, '\0', sizeof(before_name));
3734   memset(before_desc, '\0', sizeof(before_desc));
3735   memset(before_group_membership, '\0', sizeof(before_group_membership));
3736   attr_array[0] = "name";
3737   attr_array[1] = NULL;
3738   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3739                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3740     {
3741       com_err(whoami, 0, "Unable to get list name with MoiraId = %s: %s",
3742               MoiraId, ldap_err2string(rc));
3743       return(rc);
3744     }
3745   strcpy(before_name, group_base->value);
3746   linklist_free(group_base);
3747   group_base = NULL;
3748   group_count = 0;
3749   attr_array[0] = "description";
3750   attr_array[1] = NULL;
3751   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3752                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3753     {
3754       com_err(whoami, 0, 
3755               "Unable to get list description with MoiraId = %s: %s",
3756               MoiraId, ldap_err2string(rc));
3757       return(rc);
3758     }
3759   if (group_count != 0)
3760     {
3761       strcpy(before_desc, group_base->value);
3762       linklist_free(group_base);
3763       group_base = NULL;
3764       group_count = 0;
3765     }
3766   change_to_lower_case(ad_distinguishedName);  
3767   strcpy(ou_both, group_ou_both);
3768   change_to_lower_case(ou_both);
3769   strcpy(ou_security, group_ou_security);
3770   change_to_lower_case(ou_security);
3771   strcpy(ou_distribution, group_ou_distribution);
3772   change_to_lower_case(ou_distribution);
3773   strcpy(ou_neither, group_ou_neither);
3774   change_to_lower_case(ou_neither);
3775   if (strstr(ad_distinguishedName, ou_both))
3776     {
3777       strcpy(before_group_ou, group_ou_both);
3778       before_group_membership[0] = 'B';
3779       before_security_flag = 1;
3780     }
3781   else if (strstr(ad_distinguishedName, ou_security))
3782     {
3783       strcpy(before_group_ou, group_ou_security);
3784       before_group_membership[0] = 'S';
3785       before_security_flag = 1;
3786     }
3787   else if (strstr(ad_distinguishedName, ou_distribution))
3788     {
3789       strcpy(before_group_ou, group_ou_distribution);
3790       before_group_membership[0] = 'D';
3791       before_security_flag = 0;
3792     }
3793   else if (strstr(ad_distinguishedName, ou_neither))
3794     {
3795       strcpy(before_group_ou, group_ou_neither);
3796       before_group_membership[0] = 'N';
3797       before_security_flag = 0;
3798     }
3799   else
3800     return(AD_NO_OU_FOUND);
3801   rc = group_rename(ldap_handle, dn_path, before_name, before_group_membership, 
3802                     before_group_ou, before_security_flag, before_desc,
3803                     group_name, group_membership, group_ou, group_security_flag,
3804                     before_desc, MoiraId, filter);
3805   return(rc);
3806 }
3807
3808 void change_to_lower_case(char *ptr)
3809 {
3810   int i;
3811
3812   for (i = 0; i < (int)strlen(ptr); i++)
3813     {
3814       ptr[i] = tolower(ptr[i]);
3815     }
3816 }
3817
3818 int ad_get_group(LDAP *ldap_handle, char *dn_path, 
3819                  char *group_name, char *group_membership, 
3820                  char *MoiraId, char *attribute,
3821                  LK_ENTRY **linklist_base, int *linklist_count,
3822                  char *rFilter)
3823 {
3824   LK_ENTRY  *pPtr;
3825   char  filter[128];
3826   char  *attr_array[3];
3827   int   rc;
3828
3829   (*linklist_base) = NULL;
3830   (*linklist_count) = 0;
3831   if (strlen(rFilter) != 0)
3832     {
3833       strcpy(filter, rFilter);
3834       attr_array[0] = attribute;
3835       attr_array[1] = NULL;
3836       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3837                                linklist_base, linklist_count, LDAP_SCOPE_SUBTREE)) != 0)
3838         {
3839           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
3840                   MoiraId, ldap_err2string(rc));
3841          return(rc);
3842        }
3843     if ((*linklist_count) == 1)
3844       {
3845         strcpy(rFilter, filter);
3846         return(0);
3847       }
3848     }
3849
3850   linklist_free((*linklist_base));
3851   (*linklist_base) = NULL;
3852   (*linklist_count) = 0;
3853   if (strlen(MoiraId) != 0)
3854     {
3855       sprintf(filter, "(&(objectClass=group)(mitMoiraId=%s))", MoiraId);
3856       attr_array[0] = attribute;
3857       attr_array[1] = NULL;
3858       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3859                                linklist_base, linklist_count, LDAP_SCOPE_SUBTREE)) != 0)
3860         {
3861           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
3862                   MoiraId, ldap_err2string(rc));
3863          return(rc);
3864        }
3865     }
3866   if ((*linklist_count) > 1)
3867     {
3868       com_err(whoami, 0, "multiple groups with mitMoiraId = %s", MoiraId);
3869       pPtr = (*linklist_base);
3870       while (pPtr)
3871         {
3872           com_err(whoami, 0, "groups %s has mitMoiraId = %s", pPtr->value, MoiraId);
3873           pPtr = pPtr->next;
3874         }
3875       linklist_free((*linklist_base));
3876       (*linklist_base) = NULL;
3877       (*linklist_count) = 0;
3878     }
3879   if ((*linklist_count) == 1)
3880     {
3881       if (!memcmp(&(*linklist_base)->value[3], group_name, strlen(group_name)))
3882         {
3883           strcpy(rFilter, filter);
3884           return(0);
3885         }
3886     }
3887
3888   linklist_free((*linklist_base));
3889   (*linklist_base) = NULL;
3890   (*linklist_count) = 0;
3891   sprintf(filter, "(sAMAccountName=%s_group)", group_name);
3892   attr_array[0] = attribute;
3893   attr_array[1] = NULL;
3894   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3895                            linklist_base, linklist_count, LDAP_SCOPE_SUBTREE)) != 0)
3896     {
3897       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
3898               MoiraId, ldap_err2string(rc));
3899       return(rc);
3900     }
3901   if ((*linklist_count) == 1)
3902     {
3903       strcpy(rFilter, filter);
3904       return(0);
3905     }
3906
3907   return(0);
3908 }
3909
3910 int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, char *MoiraId)
3911 {
3912   char filter[128];
3913   char *attr_array[3];
3914   char SamAccountName[64];
3915   int  group_count;
3916   int  rc;
3917   LK_ENTRY  *group_base;
3918   LK_ENTRY  *gPtr;
3919
3920   group_count = 0;
3921   group_base = NULL;
3922
3923   if (strlen(MoiraId) != 0)
3924     {
3925       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
3926       attr_array[0] = "sAMAccountName";
3927       attr_array[1] = NULL;
3928       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3929                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3930         {
3931           com_err(whoami, 0, "Unable to process user %s : %s",
3932                   UserName, ldap_err2string(rc));
3933           return(rc);
3934         }
3935       if (group_count > 1)
3936         {
3937           com_err(whoami, 0, "multiple users exist with MoiraId = %s",
3938                   MoiraId);
3939           gPtr = group_base;
3940           while (gPtr)
3941             {
3942               com_err(whoami, 0, "user %s exist with MoiraId = %s",
3943                       gPtr->value, MoiraId);
3944               gPtr = gPtr->next;
3945             }
3946         }
3947     }
3948   if (group_count != 1)
3949     {
3950       linklist_free(group_base);
3951       group_count = 0;
3952       group_base = NULL;
3953       sprintf(filter, "(sAMAccountName=%s)", UserName);
3954       attr_array[0] = "sAMAccountName";
3955       attr_array[1] = NULL;
3956       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3957                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3958         {
3959           com_err(whoami, 0, "Unable to process user %s : %s",
3960                   UserName, ldap_err2string(rc));
3961           return(rc);
3962         }
3963     }
3964
3965   if (group_count != 1)
3966     {
3967       linklist_free(group_base);
3968       return(AD_NO_USER_FOUND);
3969     }
3970   strcpy(SamAccountName, group_base->value);
3971   linklist_free(group_base);
3972   group_count = 0;
3973   rc = 0;
3974   if (strcmp(SamAccountName, UserName))
3975     {
3976       rc = user_rename(ldap_handle, dn_path, SamAccountName, 
3977                        UserName);
3978     }
3979   return(0);
3980 }
3981
3982 void container_get_dn(char *src, char *dest)
3983 {
3984   char *sPtr;
3985   char *array[20];
3986   char name[256];
3987   int  n;
3988
3989   memset(array, '\0', 20 * sizeof(array[0]));
3990
3991   if (strlen(src) == 0)
3992     return;
3993   strcpy(name, src);
3994   sPtr = name;
3995   n = 0;
3996   array[n] = name;
3997   ++n;
3998   while (*sPtr)
3999     {
4000       if ((*sPtr) == '/')
4001         {
4002           (*sPtr) = '\0';
4003           ++sPtr;
4004           array[n] = sPtr;
4005           ++n;
4006         }
4007       else
4008         ++sPtr;
4009     }
4010   strcpy(dest, "OU=");
4011   while (n != 0)
4012     {
4013       strcat(dest, array[n-1]);
4014       --n;
4015       if (n > 0)
4016         {
4017           strcat(dest, ",OU=");
4018         }
4019     }
4020   return;
4021 }
4022
4023 void container_get_name(char *src, char *dest)
4024 {
4025   char *sPtr;
4026   char *dPtr;
4027
4028   if (strlen(src) == 0)
4029     return;
4030   sPtr = src;
4031   dPtr = src;
4032   while (*sPtr)
4033     {
4034       if ((*sPtr) == '/')
4035         {
4036           dPtr = sPtr;
4037           ++dPtr;
4038         }
4039       ++sPtr;
4040     }
4041   strcpy(dest, dPtr);
4042   return;
4043 }
4044
4045 void container_check(LDAP *ldap_handle, char *dn_path, char *name)
4046 {
4047   char cName[256];
4048   char *av[7];
4049   int  i;
4050   int  rc;
4051
4052   strcpy(cName, name);
4053   for (i = 0; i < (int)strlen(cName); i++)
4054     {
4055       if (cName[i] == '/')
4056         {
4057           cName[i] = '\0';
4058           av[CONTAINER_NAME] = cName;
4059           av[CONTAINER_DESC] = "";
4060           av[CONTAINER_LOCATION] = "";
4061           av[CONTAINER_CONTACT] = "";
4062           av[CONTAINER_TYPE] = "";
4063           av[CONTAINER_ID] = "";
4064           av[CONTAINER_ROWID] = "";
4065           rc = container_create(ldap_handle, dn_path, 7, av);
4066           if (rc == LDAP_SUCCESS)
4067             {
4068               com_err(whoami, 0, "container %s created without a mitMoiraId", cName);
4069             }
4070           cName[i] = '/';
4071         }
4072     }
4073
4074 }
4075
4076 int container_rename(LDAP *ldap_handle, char *dn_path, int beforec, char **before, 
4077                      int afterc, char **after)
4078 {
4079   char      dName[256];
4080   char      cName[256];
4081   char      new_cn[128];
4082   char      new_dn_path[256];
4083   char      temp[256];
4084   char      distinguishedName[256];
4085   char      *pPtr;
4086   int       rc;
4087   int       i;
4088
4089   memset(cName, '\0', sizeof(cName));
4090   container_get_name(after[CONTAINER_NAME], cName);
4091   if (!check_container_name(cName))
4092     {
4093       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4094       return(AD_INVALID_NAME);
4095     }
4096
4097   memset(distinguishedName, '\0', sizeof(distinguishedName));
4098   if (rc = container_get_distinguishedName(ldap_handle, dn_path, distinguishedName, beforec, before))
4099     return(rc);
4100   if (strlen(distinguishedName) == 0)
4101     {
4102       rc = container_create(ldap_handle, dn_path, afterc, after);
4103       return(rc);
4104     }
4105
4106   strcpy(temp, after[CONTAINER_NAME]);
4107   pPtr = temp;
4108   for (i = 0; i < (int)strlen(temp); i++)
4109     {
4110       if (temp[i] == '/')
4111         {
4112           pPtr = &temp[i];
4113         }
4114     }
4115   (*pPtr) = '\0';
4116
4117   container_get_dn(temp, dName);
4118   if (strlen(temp) != 0)
4119     sprintf(new_dn_path, "%s,%s", dName, dn_path);
4120   else
4121     sprintf(new_dn_path, "%s", dn_path);
4122   sprintf(new_cn, "OU=%s", cName);
4123
4124   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
4125
4126   if ((rc = ldap_rename_s(ldap_handle, distinguishedName, new_cn, new_dn_path,
4127                           TRUE, NULL, NULL)) != LDAP_SUCCESS)
4128     {
4129       com_err(whoami, 0, "Unable to rename container from %s to %s : %s",
4130               before[CONTAINER_NAME], after[CONTAINER_NAME], ldap_err2string(rc));
4131       return(rc);
4132     }
4133
4134   memset(dName, '\0', sizeof(dName));
4135   container_get_dn(after[CONTAINER_NAME], dName);
4136   rc = container_adupdate(ldap_handle, dn_path, dName, "", afterc, after);
4137   return(rc);
4138 }
4139
4140 int container_delete(LDAP *ldap_handle, char *dn_path, int count, char **av)
4141 {
4142   char      distinguishedName[256];
4143   int       rc;
4144
4145   memset(distinguishedName, '\0', sizeof(distinguishedName));
4146   if (rc = container_get_distinguishedName(ldap_handle, dn_path, distinguishedName, count, av))
4147     return(rc);
4148   if (strlen(distinguishedName) == 0)
4149     return(0);
4150   if ((rc = ldap_delete_s(ldap_handle, distinguishedName)) != LDAP_SUCCESS)
4151     {
4152       if (rc == LDAP_NOT_ALLOWED_ON_NONLEAF)
4153         container_move_objects(ldap_handle, dn_path, distinguishedName);
4154       else
4155         com_err(whoami, 0, "Unable to delete container %s from AD : %s",
4156                 av[CONTAINER_NAME], ldap_err2string(rc));
4157     }
4158   return(rc);
4159 }
4160
4161 int container_create(LDAP *ldap_handle, char *dn_path, int count, char **av)
4162 {
4163   char      *attr_array[3];
4164   LK_ENTRY  *group_base;
4165   int       group_count;
4166   LDAPMod   *mods[20];
4167   char      *objectClass_v[] = {"top", 
4168                            "organizationalUnit", 
4169                            NULL};
4170
4171   char *ou_v[] = {NULL, NULL};
4172   char *name_v[] = {NULL, NULL};
4173   char *moiraId_v[] = {NULL, NULL};
4174   char *desc_v[] = {NULL, NULL};
4175   char *managedBy_v[] = {NULL, NULL};
4176   char dName[256];
4177   char cName[256];
4178   char managedByDN[256];
4179   char filter[256];
4180   char temp[256];
4181   int  n;
4182   int  i;
4183   int  rc;
4184
4185   memset(filter, '\0', sizeof(filter));
4186   memset(dName, '\0', sizeof(dName));
4187   memset(cName, '\0', sizeof(cName));
4188   memset(managedByDN, '\0', sizeof(managedByDN));
4189   container_get_dn(av[CONTAINER_NAME], dName);
4190   container_get_name(av[CONTAINER_NAME], cName);
4191
4192   if ((strlen(cName) == 0) || (strlen(dName) == 0))
4193     {
4194       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4195       return(AD_INVALID_NAME);
4196     }
4197
4198   if (!check_container_name(cName))
4199     {
4200       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4201       return(AD_INVALID_NAME);
4202     }
4203
4204   n = 0;
4205   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
4206   name_v[0] = cName;
4207   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
4208   ou_v[0] = cName;
4209   ADD_ATTR("ou", ou_v, LDAP_MOD_ADD);
4210   if (strlen(av[CONTAINER_ROWID]) != 0)
4211     {
4212       moiraId_v[0] = av[CONTAINER_ROWID];
4213       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_ADD);
4214     }
4215   if (strlen(av[CONTAINER_DESC]) != 0)
4216     {
4217       desc_v[0] = av[CONTAINER_DESC];
4218       ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
4219     }
4220   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
4221     {
4222           if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
4223           {
4224                   if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], kerberos_ou))
4225                   {
4226                         sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], kerberos_ou,dn_path);
4227                         managedBy_v[0] = managedByDN;
4228                         ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
4229                   }
4230           }
4231           else
4232           {
4233                 if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
4234         {
4235           sprintf(filter, "(&(cn=%s)(&(objectCategory=person)(objectClass=user)))", av[CONTAINER_ID]);
4236         }
4237                 if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
4238         {
4239           sprintf(filter, "(&(objectClass=group)(cn=%s))", av[CONTAINER_ID]);
4240         }
4241                 if (strlen(filter) != 0)
4242         {
4243           attr_array[0] = "distinguishedName";
4244           attr_array[1] = NULL;
4245           group_count = 0;
4246           group_base = NULL;
4247           if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4248                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4249             {
4250               if (group_count == 1)
4251                 {
4252                   strcpy(managedByDN, group_base->value);
4253                   managedBy_v[0] = managedByDN;
4254                   ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
4255                 }
4256               linklist_free(group_base);
4257               group_base = NULL;
4258               group_count = 0;
4259             }
4260         }
4261     }
4262   }
4263   mods[n] = NULL;
4264
4265   sprintf(temp, "%s,%s", dName, dn_path);
4266   rc = ldap_add_ext_s(ldap_handle, temp, mods, NULL, NULL);
4267   for (i = 0; i < n; i++)
4268     free(mods[i]);
4269   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
4270     {
4271       com_err(whoami, 0, "Unable to create container %s : %s",
4272               cName, ldap_err2string(rc));
4273       return(rc);
4274     }
4275   if (rc == LDAP_ALREADY_EXISTS)
4276     {
4277       if (strlen(av[CONTAINER_ROWID]) != 0)
4278         rc = container_adupdate(ldap_handle, dn_path, dName, "", count, av);
4279     }
4280   return(rc);
4281 }
4282
4283 int container_update(LDAP *ldap_handle, char *dn_path, int beforec, char **before, 
4284                      int afterc, char **after)
4285 {
4286   char distinguishedName[256];
4287   int  rc;
4288
4289   memset(distinguishedName, '\0', sizeof(distinguishedName));
4290   if (rc = container_get_distinguishedName(ldap_handle, dn_path, distinguishedName, afterc, after))
4291     return(rc);
4292   if (strlen(distinguishedName) == 0)
4293     {
4294       rc = container_create(ldap_handle, dn_path, afterc, after);
4295       return(rc);
4296     }
4297
4298   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
4299   rc = container_adupdate(ldap_handle, dn_path, "", distinguishedName, afterc, after);
4300
4301   return(rc);
4302 }
4303
4304 int container_get_distinguishedName(LDAP *ldap_handle, char *dn_path, char *distinguishedName, int count, char **av)
4305 {
4306   char      *attr_array[3];
4307   LK_ENTRY  *group_base;
4308   int       group_count;
4309   char      dName[256];
4310   char      cName[256];
4311   char      filter[512];
4312   int       rc;
4313
4314   memset(filter, '\0', sizeof(filter));
4315   memset(dName, '\0', sizeof(dName));
4316   memset(cName, '\0', sizeof(cName));
4317   container_get_dn(av[CONTAINER_NAME], dName);
4318   container_get_name(av[CONTAINER_NAME], cName);
4319
4320   if (strlen(dName) == 0)
4321     {
4322       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", av[CONTAINER_NAME]);
4323       return(AD_INVALID_NAME);
4324     }
4325
4326   if (!check_container_name(cName))
4327     {
4328       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4329       return(AD_INVALID_NAME);
4330     }
4331
4332   sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", av[CONTAINER_ROWID]);
4333   attr_array[0] = "distinguishedName";
4334   attr_array[1] = NULL;
4335   group_count = 0;
4336   group_base = NULL;
4337   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4338                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4339     {
4340       if (group_count == 1)
4341         {
4342           strcpy(distinguishedName, group_base->value);
4343         }
4344       linklist_free(group_base);
4345       group_base = NULL;
4346       group_count = 0;
4347     }
4348   if (strlen(distinguishedName) == 0)
4349     {
4350       sprintf(filter, "(&(objectClass=organizationalUnit)(distinguishedName=%s,%s))", dName, dn_path);
4351       attr_array[0] = "distinguishedName";
4352       attr_array[1] = NULL;
4353       group_count = 0;
4354       group_base = NULL;
4355       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4356                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4357         {
4358           if (group_count == 1)
4359             {
4360               strcpy(distinguishedName, group_base->value);
4361             }
4362           linklist_free(group_base);
4363           group_base = NULL;
4364           group_count = 0;
4365         }
4366     }
4367   return(0);
4368 }
4369
4370 int container_adupdate(LDAP *ldap_handle, char *dn_path, char *dName, 
4371                        char *distinguishedName, int count, char **av)
4372 {
4373   char      *attr_array[5];
4374   LK_ENTRY  *group_base;
4375   LK_ENTRY  *pPtr;
4376   LDAPMod   *mods[20];
4377   int       group_count;
4378   char      filter[512];
4379   char      *moiraId_v[] = {NULL, NULL};
4380   char      *desc_v[] = {NULL, NULL};
4381   char      *managedBy_v[] = {NULL, NULL};
4382   char      managedByDN[256];
4383   char      moiraId[64];
4384   char      desc[256];
4385   char      ad_path[512];
4386   int       rc;
4387   int       i;
4388   int       n;
4389
4390
4391   strcpy(ad_path, distinguishedName);
4392   if (strlen(dName) != 0)
4393     sprintf(ad_path, "%s,%s", dName, dn_path);
4394
4395   sprintf(filter, "(&(objectClass=organizationalUnit)(distinguishedName=%s))", ad_path);
4396   if (strlen(av[CONTAINER_ID]) != 0)
4397     sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", av[CONTAINER_ROWID]);
4398   attr_array[0] = "mitMoiraId";
4399   attr_array[1] = "description";
4400   attr_array[2] = "managedBy";
4401   attr_array[3] = NULL;
4402   group_count = 0;
4403   group_base = NULL;
4404   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4405                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
4406     {
4407       com_err(whoami, 0, "Unable to retreive container info for %s : %s",
4408               av[CONTAINER_NAME], ldap_err2string(rc));
4409       return(rc);
4410     }
4411   memset(managedByDN, '\0', sizeof(managedByDN));
4412   memset(moiraId, '\0', sizeof(moiraId));
4413   memset(desc, '\0', sizeof(desc));
4414   pPtr = group_base;
4415   while (pPtr)
4416     {
4417       if (!strcasecmp(pPtr->attribute, "description"))
4418         strcpy(desc, pPtr->value);
4419       else if (!strcasecmp(pPtr->attribute, "managedBy"))
4420         strcpy(managedByDN, pPtr->value);
4421       else if (!strcasecmp(pPtr->attribute, "mitMoiraId"))
4422         strcpy(moiraId, pPtr->value);
4423       pPtr = pPtr->next;
4424     }
4425   linklist_free(group_base);
4426   group_base = NULL;
4427   group_count = 0;
4428
4429   n = 0;
4430   if (strlen(av[CONTAINER_ROWID]) != 0)
4431     {
4432       moiraId_v[0] = av[CONTAINER_ROWID];
4433       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_REPLACE);
4434     }
4435   if (strlen(av[CONTAINER_DESC]) != 0)
4436     {
4437       attribute_update(ldap_handle, ad_path, av[CONTAINER_DESC], "description", dName);
4438     }
4439   else
4440     {
4441       if (strlen(desc) != 0)
4442         {
4443           attribute_update(ldap_handle, ad_path, "", "description", dName);
4444         }
4445     }
4446   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
4447     {
4448           if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
4449           {
4450                   if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], kerberos_ou))
4451                   {
4452                         sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], kerberos_ou, dn_path);
4453                         managedBy_v[0] = managedByDN;
4454             ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
4455                   }
4456                   else
4457                   {
4458                         if (strlen(managedByDN) != 0)
4459                         {
4460                 attribute_update(ldap_handle, ad_path, "", "managedBy", dName);
4461                         }
4462                   }
4463           }
4464           else
4465           {
4466                 memset(filter, '\0', sizeof(filter));
4467                 if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
4468         {
4469           sprintf(filter, "(&(cn=%s)(&(objectCategory=person)(objectClass=user)))", av[CONTAINER_ID]);
4470         }
4471                 if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
4472         {
4473           sprintf(filter, "(&(objectClass=group)(cn=%s))", av[CONTAINER_ID]);
4474         }
4475                 if (strlen(filter) != 0)
4476         {
4477           attr_array[0] = "distinguishedName";
4478           attr_array[1] = NULL;
4479           group_count = 0;
4480           group_base = NULL;
4481           if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4482                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4483             {
4484               if (group_count == 1)
4485                 {
4486                   strcpy(managedByDN, group_base->value);
4487                   managedBy_v[0] = managedByDN;
4488                   ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
4489                 }
4490               else
4491                 {
4492                   if (strlen(managedByDN) != 0)
4493                     {
4494                         attribute_update(ldap_handle, ad_path, "", "managedBy", dName);
4495                     }
4496                 }
4497               linklist_free(group_base);
4498               group_base = NULL;
4499               group_count = 0;
4500             }
4501         }
4502                 else
4503         {
4504           if (strlen(managedByDN) != 0)
4505             {
4506                 attribute_update(ldap_handle, ad_path, "", "managedBy", dName);
4507             }
4508         }
4509           }
4510     }
4511   mods[n] = NULL;
4512   if (n == 0)
4513     return(LDAP_SUCCESS);
4514
4515   rc = ldap_modify_s(ldap_handle, ad_path, mods);
4516   for (i = 0; i < n; i++)
4517     free(mods[i]);
4518   if (rc != LDAP_SUCCESS)
4519     {
4520         com_err(whoami, 0, "Unable to modify container info for %s : %s",
4521                 av[CONTAINER_NAME], ldap_err2string(rc));
4522         return(rc);
4523     }
4524   return(rc);
4525 }
4526
4527 int container_move_objects(LDAP *ldap_handle, char *dn_path, char *dName)
4528 {
4529   char      *attr_array[3];
4530   LK_ENTRY  *group_base;
4531   LK_ENTRY  *pPtr;
4532   int       group_count;
4533   char      filter[512];
4534   char      new_cn[128];
4535   char      temp[256];
4536   int       rc;
4537   int       NumberOfEntries = 10;
4538   int       i;
4539   int       count;
4540
4541   rc = ldap_set_option(ldap_handle, LDAP_OPT_SIZELIMIT, &NumberOfEntries);
4542
4543   for (i = 0; i < 3; i++)
4544     {
4545       memset(filter, '\0', sizeof(filter));
4546       if (i == 0)
4547         {
4548           strcpy(filter, "(!(|(objectClass=computer)(objectClass=organizationalUnit)))");
4549           attr_array[0] = "cn";
4550           attr_array[1] = NULL;
4551         }
4552       else if (i == 1)
4553         {
4554           strcpy(filter, "(objectClass=computer)");
4555           attr_array[0] = "cn";
4556           attr_array[1] = NULL;
4557         }
4558       else
4559         {
4560           strcpy(filter, "(objectClass=organizationalUnit)");
4561           attr_array[0] = "ou";
4562           attr_array[1] = NULL;
4563         }
4564
4565       while (1)
4566         {
4567           if ((rc = linklist_build(ldap_handle, dName, filter, attr_array, 
4568                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
4569             {
4570               break;
4571             }
4572           if (group_count == 0)
4573             break;
4574           pPtr = group_base;
4575           while(pPtr)
4576             {
4577               if (!strcasecmp(pPtr->attribute, "cn"))
4578                 {
4579                   sprintf(new_cn, "cn=%s", pPtr->value);
4580                   if (i == 0)
4581                     sprintf(temp, "%s,%s", orphans_other_ou, dn_path);
4582                   if (i == 1)
4583                     sprintf(temp, "%s,%s", orphans_machines_ou, dn_path);
4584                   count = 1;
4585                   while (1)
4586                     {
4587                       rc = ldap_rename_s(ldap_handle, pPtr->dn, new_cn, temp,
4588                                          TRUE, NULL, NULL);
4589                       if (rc == LDAP_ALREADY_EXISTS)
4590                         {
4591                           sprintf(new_cn, "cn=%s_%d", pPtr->value, count);
4592                           ++count;
4593                         }
4594                       else
4595                         break;
4596                     }
4597                 }
4598               else if (!strcasecmp(pPtr->attribute, "ou"))
4599                 {
4600                   rc = ldap_delete_s(ldap_handle, pPtr->dn);
4601                 }
4602               pPtr = pPtr->next;
4603             }
4604           linklist_free(group_base);
4605           group_base = NULL;
4606           group_count = 0;
4607         }
4608     }
4609   return(0);
4610 }
4611
4612 int get_machine_ou(LDAP *ldap_handle, char *dn_path, char *member, char *machine_ou, char *NewMachineName)
4613 {
4614   LK_ENTRY  *group_base;
4615   int  group_count;
4616   int  i;
4617   char filter[128];
4618   char *attr_array[3];
4619   char cn[256];
4620   char dn[256];
4621   char temp[256];
4622   char *pPtr;
4623   int   rc;
4624
4625   strcpy(NewMachineName, member);
4626   rc = moira_connect();
4627   rc = GetMachineName(NewMachineName);
4628   moira_disconnect();
4629   if (strlen(NewMachineName) == 0)
4630     {
4631       com_err(whoami, 0, "Unable to find alais for machine %s in Moira", member);
4632       return(1);
4633     }
4634
4635   pPtr = NULL;
4636   pPtr = strchr(NewMachineName, '.');
4637   if (pPtr != NULL)
4638     (*pPtr) = '\0';
4639
4640   group_base = NULL;
4641   group_count = 0;
4642   sprintf(filter, "(sAMAccountName=%s$)", NewMachineName);
4643   attr_array[0] = "cn";
4644   attr_array[1] = NULL;
4645   sprintf(temp, "%s", dn_path);
4646   if ((rc = linklist_build(ldap_handle, temp, filter, attr_array, 
4647                         &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
4648     {
4649       com_err(whoami, 0, "Unable to process machine %s : %s",
4650               member, ldap_err2string(rc));
4651       return(1);
4652     }
4653   if (group_count != 1)
4654     {
4655       com_err(whoami, 0, "Unable to process machine %s : machine not found in AD",
4656               NewMachineName);
4657       return(1);
4658     }
4659   strcpy(dn, group_base->dn);
4660   strcpy(cn, group_base->value);
4661   for (i = 0; i < (int)strlen(dn); i++)
4662     dn[i] = tolower(dn[i]);
4663   for (i = 0; i < (int)strlen(cn); i++)
4664     cn[i] = tolower(cn[i]);
4665   linklist_free(group_base);
4666   pPtr = NULL;
4667   pPtr = strstr(dn, cn);
4668   if (pPtr == NULL)
4669     {
4670       com_err(whoami, 0, "Unable to process machine %s",
4671               member);
4672       return(1);
4673     }
4674   pPtr += strlen(cn) + 1;
4675   strcpy(machine_ou, pPtr);
4676   pPtr = NULL;
4677   pPtr = strstr(machine_ou, "dc=");
4678   if (pPtr == NULL)
4679     {
4680       com_err(whoami, 0, "Unable to process machine %s",
4681               member);
4682       return(1);
4683     }
4684   --pPtr;
4685   (*pPtr) = '\0';
4686   return(0);
4687 }
4688
4689 int machine_move_to_ou(LDAP *ldap_handle, char * dn_path, char *MoiraMachineName, char *DestinationOu)
4690 {
4691
4692     char        NewCn[128];
4693     char        OldDn[512];
4694     char        MachineName[128];
4695     char        filter[128];
4696     char        *attr_array[3];
4697     char        NewOu[256];
4698     char        *cPtr = NULL;
4699     int         group_count;
4700     long        rc;
4701     LK_ENTRY    *group_base;
4702
4703     group_count = 0;
4704     group_base = NULL;
4705
4706     strcpy(MachineName, MoiraMachineName);
4707     rc = GetMachineName(MachineName);
4708     if (strlen(MachineName) == 0)
4709     {
4710         com_err(whoami, 0, "Unable to find alais for machine %s in Moira", MoiraMachineName);
4711         return(1);
4712     }
4713
4714     cPtr = strchr(MachineName, '.');
4715     if (cPtr != NULL)
4716         (*cPtr) = '\0';
4717     sprintf(filter, "(sAMAccountName=%s$)", MachineName);
4718     attr_array[0] = "sAMAccountName";
4719     attr_array[1] = NULL;
4720     if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, &group_base, 
4721                              &group_count, LDAP_SCOPE_SUBTREE)) != 0)
4722     {
4723         com_err(whoami, 0, "Unable to process machine %s : %s",
4724                 MoiraMachineName, ldap_err2string(rc));
4725         return(1);
4726     }
4727
4728     if (group_count == 1)
4729         strcpy(OldDn, group_base->dn);
4730     linklist_free(group_base);
4731     group_base = NULL;
4732     if (group_count != 1)
4733     {
4734         com_err(whoami, 0, "Unable to find machine %s in AD: %s", MoiraMachineName);
4735         return(1);
4736     }
4737     sprintf(NewOu, "%s,%s", DestinationOu, dn_path);
4738     cPtr = strchr(OldDn, ',');
4739     if (cPtr != NULL)
4740     {
4741         ++cPtr;
4742         if (!strcasecmp(cPtr, NewOu))
4743             return(0);
4744     }
4745     sprintf(NewCn, "CN=%s", MachineName);
4746     rc = ldap_rename_s(ldap_handle, OldDn, NewCn, NewOu, TRUE, NULL, NULL);
4747     return(rc);
4748 }
4749
4750 int machine_check(LDAP *ldap_handle, char *dn_path, char *machine_name)
4751 {
4752     char    Name[128];
4753     char    *pPtr;
4754     int     rc;
4755
4756     memset(Name, '\0', sizeof(Name));
4757     strcpy(Name, machine_name);
4758     pPtr = NULL;
4759     pPtr = strchr(Name, '.');
4760     if (pPtr != NULL)
4761         (*pPtr) = '\0';
4762     strcat(Name, "$");
4763     return(!(rc = checkADname(ldap_handle, dn_path, Name)));
4764 }
4765
4766 int machine_get_moira_container(LDAP *ldap_handle, char *dn_path, char *machine_name, char *container_name)
4767 {
4768     int     rc;
4769     char    *av[2];
4770     char    *call_args[2];
4771
4772     av[0] = machine_name;
4773     call_args[0] = (char *)container_name;
4774     rc = mr_query("get_machine_to_container_map", 1, av, machine_GetMoiraContainer,
4775                    call_args);
4776     return(rc);
4777 }
4778
4779 int machine_GetMoiraContainer(int ac, char **av, void *ptr)
4780 {
4781     char **call_args;
4782     
4783     call_args = ptr;
4784     strcpy(call_args[0], av[1]);
4785     return(0);
4786 }
4787
4788 int Moira_container_group_create(char **after)
4789 {
4790   long rc;
4791   char GroupName[64];
4792   char *argv[20];
4793   
4794   memset(GroupName, '\0', sizeof(GroupName));
4795   rc = Moira_groupname_create(GroupName, after[CONTAINER_NAME], 
4796                               after[CONTAINER_ROWID]);
4797   if (rc)
4798     return rc;
4799   
4800   argv[L_NAME] = GroupName;
4801   argv[L_ACTIVE] = "1";
4802   argv[L_PUBLIC] = "0";
4803   argv[L_HIDDEN] = "0";
4804   argv[L_MAILLIST] = "0";
4805   argv[L_GROUP] = "1";
4806   argv[L_GID] = UNIQUE_GID;
4807   argv[L_NFSGROUP] = "0";
4808   argv[L_MAILMAN] = "0";
4809   argv[L_MAILMAN_SERVER] = "[NONE]";
4810   argv[L_DESC] = "auto created container group";
4811   argv[L_ACE_TYPE] = "USER";
4812   argv[L_MEMACE_TYPE] = "USER";
4813   argv[L_ACE_NAME] = "sms";
4814   argv[L_MEMACE_NAME] = "sms";
4815
4816   if (rc = mr_query("add_list", 15, argv, NULL, NULL))
4817     {
4818       com_err(whoami, 0, "Unable to create container group %s for container %s: %s",
4819               GroupName, after[CONTAINER_NAME], error_message(rc));
4820     }
4821
4822   Moira_setContainerGroup(after[CONTAINER_NAME], GroupName);
4823   Moira_addGroupToParent(after[CONTAINER_NAME], GroupName);
4824   
4825   return(rc);
4826 }
4827
4828 int Moira_container_group_update(char **before, char **after)
4829 {
4830   long rc;
4831   char BeforeGroupName[64];
4832   char AfterGroupName[64];
4833   char *argv[20];
4834   
4835   if (!strcasecmp(after[CONTAINER_NAME], before[CONTAINER_NAME]))
4836     return(0);
4837
4838   memset(BeforeGroupName, '\0', sizeof(BeforeGroupName));
4839   Moira_getGroupName(after[CONTAINER_NAME], BeforeGroupName, 0);
4840   if (strlen(BeforeGroupName) == 0)
4841     return(0);
4842
4843   memset(AfterGroupName, '\0', sizeof(AfterGroupName));
4844   rc = Moira_groupname_create(AfterGroupName, after[CONTAINER_NAME], 
4845                               after[CONTAINER_ROWID]);
4846   if (rc)
4847     return rc;
4848
4849   if (strcasecmp(BeforeGroupName, AfterGroupName))
4850     {
4851       argv[L_NAME] = BeforeGroupName;
4852       argv[L_NAME + 1] = AfterGroupName;
4853       argv[L_ACTIVE + 1] = "1";
4854       argv[L_PUBLIC + 1] = "0";
4855       argv[L_HIDDEN + 1] = "0";
4856       argv[L_MAILLIST + 1] = "0";
4857       argv[L_GROUP + 1] = "1";
4858       argv[L_GID + 1] = UNIQUE_GID;
4859       argv[L_NFSGROUP + 1] = "0";
4860       argv[L_MAILMAN + 1] = "0";
4861       argv[L_MAILMAN_SERVER + 1] = "[NONE]";
4862       argv[L_DESC + 1] = "auto created container group";
4863       argv[L_ACE_TYPE + 1] = "USER";
4864       argv[L_MEMACE_TYPE + 1] = "USER";
4865       argv[L_ACE_NAME + 1] = "sms";
4866       argv[L_MEMACE_NAME + 1] = "sms";
4867       
4868       if (rc = mr_query("update_list", 16, argv, NULL, NULL))
4869         {
4870           com_err(whoami, 0, "Unable to rename container group from %s to %s: %s",
4871                   BeforeGroupName, AfterGroupName, error_message(rc));
4872         }
4873     }
4874   
4875   return(rc);
4876 }
4877
4878 int Moira_container_group_delete(char **before)
4879 {
4880   long rc = 0;
4881   char *argv[13];
4882   char GroupName[64];
4883   char ParentGroupName[64];
4884   
4885   memset(ParentGroupName, '\0', sizeof(ParentGroupName));
4886   Moira_getGroupName(before[CONTAINER_NAME], ParentGroupName, 1);
4887
4888   memset(GroupName, '\0', sizeof(GroupName));
4889   if (strcmp(before[CONTAINER_GROUP_NAME], "[none]"))
4890     strcpy(GroupName, before[CONTAINER_GROUP_NAME]);
4891   
4892   if ((strlen(ParentGroupName) != 0) && (strlen(GroupName) != 0))
4893     {
4894       argv[0] = ParentGroupName;
4895       argv[1] = "LIST";
4896       argv[2] = GroupName;
4897       if (rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL))
4898         {
4899           com_err(whoami, 0, "Unable to delete container group %s from list: %s",
4900                   GroupName, ParentGroupName, error_message(rc));
4901         }
4902     }
4903   
4904   if (strlen(GroupName) != 0)
4905     {
4906       argv[0] = GroupName;
4907       if (rc = mr_query("delete_list", 1, argv, NULL, NULL))
4908         {
4909           com_err(whoami, 0, "Unable to delete container group %s : %s",
4910                   GroupName, error_message(rc));
4911         }
4912      }
4913   
4914   return(rc);
4915 }
4916
4917 int Moira_groupname_create(char *GroupName, char *ContainerName,
4918                            char *ContainerRowID)
4919 {
4920   char *ptr;
4921   char *ptr1;
4922   char temp[64];
4923   char newGroupName[64];
4924   char tempGroupName[64];
4925   char tempgname[64];
4926   char *argv[1];
4927   int  i;
4928   long rc;
4929
4930   strcpy(temp, ContainerName);
4931   
4932   ptr1 = strrchr(temp, '/');
4933   if (ptr1 != NULL)
4934   {
4935     *ptr1 = '\0';
4936     ptr = ++ptr1;
4937     ptr1 = strrchr(temp, '/');
4938     if (ptr1 != NULL)
4939     {
4940         sprintf(tempgname, "%s-%s", ++ptr1, ptr);
4941     }
4942     else
4943         strcpy(tempgname, ptr);
4944   }
4945   else
4946     strcpy(tempgname, temp);
4947
4948   if (strlen(tempgname) > 25)
4949     tempgname[25] ='\0';
4950
4951   sprintf(newGroupName, "cnt-%s", tempgname);
4952
4953   /* change everything to lower case */
4954   ptr = newGroupName;
4955   while (*ptr)
4956     {
4957       if (isupper(*ptr))
4958         *ptr = tolower(*ptr);
4959       if (*ptr == ' ')
4960         *ptr = '-';
4961       ptr++;
4962     }
4963
4964   strcpy(tempGroupName, newGroupName);
4965   i = (int)'0';
4966   /* append 0-9 then a-z if a duplicate is found */
4967   while(1)
4968     {
4969       argv[0] = newGroupName;
4970       if (rc = mr_query("get_list_info", 1, argv, NULL, NULL))
4971         {
4972           if (rc == MR_NO_MATCH)
4973             break;
4974           com_err(whoami, 0, "Moira error while creating group name for container %s : %s",
4975                   ContainerName, error_message(rc));
4976           return rc;
4977         }
4978       sprintf(newGroupName, "%s-%c", tempGroupName, i);
4979       if (i == (int)'z')
4980         {
4981           com_err(whoami, 0, "Unable to find a unique group name for container %s: too many duplicate container names",
4982                   ContainerName);
4983           return 1;
4984         }
4985       if (i == '9')
4986         i = 'a';
4987       else
4988         i++;
4989     }
4990
4991   strcpy(GroupName, newGroupName);
4992   return(0);
4993 }
4994
4995 int Moira_setContainerGroup(char *origContainerName, char *GroupName)
4996 {
4997   long rc;
4998   char *argv[3];
4999   
5000   argv[0] = origContainerName;
5001   argv[1] = GroupName;
5002
5003   if ((rc = mr_query("set_container_list", 2, argv, NULL, NULL)))
5004     {
5005          com_err(whoami, 0, "Unable to set container group %s in container %s: %s",
5006                  GroupName, origContainerName, error_message(rc));
5007     }
5008
5009   return(0);
5010 }
5011
5012  int Moira_addGroupToParent(char *origContainerName, char *GroupName)
5013  {
5014    char ContainerName[64];
5015    char ParentGroupName[64];
5016    char *argv[3];
5017    long rc;
5018
5019    strcpy(ContainerName, origContainerName);
5020
5021    Moira_getGroupName(ContainerName, ParentGroupName, 1);
5022    /* top-level container */
5023    if (strlen(ParentGroupName) == 0)
5024      return(0);
5025    
5026    argv[0] = ParentGroupName;
5027    argv[1] = "LIST";
5028    argv[2] = GroupName;
5029    if ((rc = mr_query("add_member_to_list", 3, argv, NULL, NULL)))
5030      {
5031        com_err(whoami, 0, "Unable to add container group %s to parent group %s: %s",
5032                GroupName, ParentGroupName, error_message(rc));
5033      }
5034    return(0);
5035  }
5036
5037 int Moira_getContainerGroup(int ac, char **av, void *ptr)
5038 {
5039   char **call_args;
5040   
5041   call_args = ptr;
5042   strcpy(call_args[0], av[1]);
5043   return(0);
5044 }
5045
5046 int Moira_getGroupName(char *origContainerName, char *GroupName,
5047                        int ParentFlag)
5048 {
5049   char ContainerName[64];
5050   char *argv[3];
5051   char *call_args[3];
5052   char *ptr;
5053   long rc;
5054
5055   strcpy(ContainerName, origContainerName);
5056
5057   if (ParentFlag)
5058     {
5059       ptr = strrchr(ContainerName, '/');
5060       if (ptr != NULL)
5061         (*ptr) = '\0';
5062       else
5063         return(0);
5064     }
5065
5066   argv[0] = ContainerName;
5067   argv[1] = NULL;
5068   call_args[0] = GroupName;
5069   call_args[1] = NULL;
5070
5071   if (!(rc = mr_query("get_container_list", 1, argv, Moira_getContainerGroup,
5072                       call_args)))
5073     {
5074       if (strlen(GroupName) != 0)
5075         return(0);
5076     }
5077
5078   if (rc)
5079     com_err(whoami, 0, "Unable to get container group from container %s: %s",
5080             ContainerName, error_message(rc));
5081   else
5082     com_err(whoami, 0, "Unable to get container group from container %s",
5083             ContainerName);
5084      return(0);
5085 }
5086
5087 int Moira_process_machine_container_group(char *MachineName, char* GroupName, 
5088                                           int DeleteMachine)
5089 {
5090   char *argv[3];
5091   long rc;
5092
5093   if (strcmp(GroupName, "[none]") == 0)
5094     return 0;
5095
5096   argv[0] = GroupName;
5097   argv[1] = "MACHINE";
5098   argv[2] = MachineName;
5099   if (!DeleteMachine)
5100     rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
5101   else
5102     rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
5103   if (rc)
5104     {
5105       com_err(whoami, 0, "Unable to add machine %s to container group%s: %s",
5106               MachineName, GroupName, error_message(rc));
5107     }
5108   return(0);
5109 }
5110
5111 int GetMachineName(char *MachineName)
5112 {
5113         char    *args[2];
5114     char    NewMachineName[1024];
5115     char    *szDot;
5116     int     rc = 0;
5117     int     i;
5118     DWORD   dwLen = 0;
5119     char    *call_args[2];
5120
5121     // If the address happens to be in the top-level MIT domain, great!
5122     strcpy(NewMachineName, MachineName);
5123     for (i = 0; i < (int)strlen(NewMachineName); i++)
5124         NewMachineName[i] = toupper(NewMachineName[i]);
5125     szDot = strchr(NewMachineName,'.');
5126     if ((szDot) && (!strcasecmp(szDot+1, DOMAIN_SUFFIX)))
5127     {
5128         return(0);
5129     }
5130         
5131     // If not, see if it has a Moira alias in the top-level MIT domain.
5132     memset(NewMachineName, '\0', sizeof(NewMachineName));
5133         args[0] = "*";
5134     args[1] = MachineName;
5135     call_args[0] = NewMachineName;
5136     call_args[1] = NULL;
5137     if (rc = mr_query("get_hostalias", 2, args, ProcessMachineName, call_args))
5138     {
5139         com_err(whoami, 0, "Unable to resolve machine name %s : %s",
5140                 MachineName, error_message(rc));
5141         strcpy(MachineName, "");
5142         return(0);
5143     }
5144
5145     if (strlen(NewMachineName) != 0)
5146         strcpy(MachineName, NewMachineName);
5147     else
5148         strcpy(MachineName, "");
5149     return(0);
5150
5151 }
5152
5153 int ProcessMachineName(int ac, char **av, void *ptr)
5154 {
5155     char    **call_args;
5156     char    MachineName[1024];
5157     char    *szDot;
5158     int     i;
5159
5160     call_args = ptr;
5161     if (strlen(call_args[0]) == 0)
5162     {
5163         strcpy(MachineName, av[0]);
5164         for (i = 0; i < (int)strlen(MachineName); i++)
5165             MachineName[i] = toupper(MachineName[i]);
5166         szDot = strchr(MachineName,'.');
5167         if ((szDot) && (!strcasecmp(szDot+1,DOMAIN_SUFFIX)))
5168         {
5169             strcpy(call_args[0], MachineName);
5170         }
5171     }
5172     return(0);
5173 }
5174
5175 void SwitchSFU(LDAPMod **mods, int *UseSFU30, int n)
5176 {
5177     int i;
5178
5179     if (*UseSFU30)
5180     {
5181         for (i = 0; i < n; i++)
5182         {
5183             if (!strcmp(mods[i]->mod_type, "msSFU30UidNumber"))
5184                 mods[i]->mod_type = "uidNumber";
5185         }
5186         (*UseSFU30) = 0;
5187     }
5188     else
5189     {
5190         for (i = 0; i < n; i++)
5191         {
5192             if (!strcmp(mods[i]->mod_type, "uidNumber"))
5193                 mods[i]->mod_type = "msSFU30UidNumber";
5194         }
5195         (*UseSFU30) = 1;
5196     }
5197 }
5198
5199 int SetHomeDirectory(LDAP *ldap_handle, char *user_name, char *DistinguishedName,
5200                      char *WinHomeDir, char *WinProfileDir,
5201                      char **homedir_v, char **winProfile_v,
5202                      char **drives_v, LDAPMod **mods, 
5203                      int OpType, int n)
5204 {
5205     char **hp;
5206     char cWeight[3];
5207     char cPath[1024];
5208     char path[1024];
5209     char winPath[1024];
5210     char winProfile[1024];
5211     char homeDrive[8];
5212     int  last_weight;
5213     int  i;
5214     int  rc;
5215     LDAPMod *DelMods[20];
5216
5217     memset(homeDrive, '\0', sizeof(homeDrive));
5218     memset(path, '\0', sizeof(path));
5219     memset(winPath, '\0', sizeof(winPath));
5220     memset(winProfile, '\0', sizeof(winProfile));
5221     hp = NULL;
5222     if ((!strcasecmp(WinHomeDir, "[afs]")) || (!strcasecmp(WinProfileDir, "[afs]")))
5223     {
5224         if ((hp = hes_resolve(user_name, "filsys")) != NULL)
5225         {
5226             memset(cWeight, 0, sizeof(cWeight));
5227             memset(cPath, 0, sizeof(cPath));
5228             last_weight = 1000;
5229             i = 0;
5230             while (hp[i] != NULL)
5231             {
5232                 if (sscanf(hp[i], "%*s %s", cPath))
5233                 {
5234                     if (strnicmp(cPath, AFS, strlen(AFS)) == 0)
5235                     {
5236                         if (sscanf(hp[i], "%*s %*s %*s %*s %s", cWeight))
5237                         {
5238                             if (atoi(cWeight) < last_weight)
5239                             {
5240                                 strcpy(path, cPath);
5241                                 last_weight = (int)atoi(cWeight);
5242                             }
5243                         }
5244                         else 
5245                             strcpy(path, cPath);
5246                     }
5247                 }
5248               ++i;
5249             }
5250             if (strlen(path))
5251             {
5252                 if (!strnicmp(path, AFS, strlen(AFS)))
5253                 {
5254                     AfsToWinAfs(path, winPath);
5255                     strcpy(winProfile, winPath);
5256                     strcat(winProfile, "\\.winprofile");
5257                 }
5258             }
5259         }
5260         else
5261             return(n);
5262     }
5263
5264     if ((!strcasecmp(WinHomeDir, "[dfs]")) || (!strcasecmp(WinProfileDir, "[dfs]")))
5265     {
5266         sprintf(path, "\\\\%s\\dfs\\profiles\\%c\\%s", ldap_domain, user_name[0], user_name);
5267         if (!strcasecmp(WinProfileDir, "[dfs]"))
5268           {
5269             strcpy(winProfile, path);
5270             strcat(winProfile, "\\.winprofile");
5271           }
5272         if (!strcasecmp(WinHomeDir, "[dfs]"))
5273           strcpy(winPath, path);
5274     }
5275
5276     if (hp != NULL)
5277     {
5278         i = 0;
5279         while (hp[i])
5280         {
5281             free(hp[i]);
5282             i++;
5283         }
5284     }
5285
5286     if (!strcasecmp(WinHomeDir, "[local]"))
5287         memset(winPath, '\0', sizeof(winPath));
5288     else if (!strcasecmp(WinHomeDir, "[afs]") || !strcasecmp(WinHomeDir, "[dfs]"))
5289     {
5290         strcpy(homeDrive, "H:");
5291     }
5292     else
5293     {
5294         strcpy(winPath, WinHomeDir);
5295         if (!strncmp(WinHomeDir, "\\\\", 2))
5296         {
5297             strcpy(homeDrive, "H:");
5298         }        
5299     }
5300
5301     // nothing needs to be done if WinProfileDir is [afs].
5302     if (!strcasecmp(WinProfileDir, "[local]"))
5303         memset(winProfile, '\0', sizeof(winProfile));
5304     else if (strcasecmp(WinProfileDir, "[afs]") && strcasecmp(WinProfileDir, "[dfs]"))
5305     {
5306         strcpy(winProfile, WinProfileDir);
5307     }
5308
5309     if (strlen(winProfile) != 0)
5310     {
5311         if (winProfile[strlen(winProfile) - 1] == '\\')
5312             winProfile[strlen(winProfile) - 1] = '\0';
5313     }
5314     if (strlen(winPath) != 0)
5315     {
5316         if (winPath[strlen(winPath) - 1] == '\\')
5317             winPath[strlen(winPath) - 1] = '\0';
5318     }
5319
5320     if ((winProfile[1] == ':') && (strlen(winProfile) == 2))
5321         strcat(winProfile, "\\");
5322     if ((winPath[1] == ':') && (strlen(winPath) == 2))
5323         strcat(winPath, "\\");
5324
5325     if (strlen(winPath) == 0)
5326     {
5327         if (OpType == LDAP_MOD_REPLACE)
5328         {
5329             i = 0;
5330             DEL_ATTR("homeDirectory", LDAP_MOD_DELETE);
5331             DelMods[i] = NULL;
5332             //unset homeDirectory attribute for user.
5333             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
5334             free(DelMods[0]);
5335         }
5336     }
5337     else
5338     {
5339         homedir_v[0] = strdup(winPath);
5340         ADD_ATTR("homeDirectory", homedir_v, OpType);
5341     }
5342
5343     if (strlen(winProfile) == 0)
5344     {
5345         if (OpType == LDAP_MOD_REPLACE)
5346         {
5347             i = 0;
5348             DEL_ATTR("profilePath", LDAP_MOD_DELETE);
5349             DelMods[i] = NULL;
5350             //unset profilePate attribute for user.
5351             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
5352             free(DelMods[0]);
5353         }
5354     }
5355     else
5356     {
5357         winProfile_v[0] = strdup(winProfile);
5358         ADD_ATTR("profilePath", winProfile_v, OpType);
5359     }
5360
5361     if (strlen(homeDrive) == 0)
5362     {
5363         if (OpType == LDAP_MOD_REPLACE)
5364         {
5365             i = 0;
5366             DEL_ATTR("homeDrive", LDAP_MOD_DELETE);
5367             DelMods[i] = NULL;
5368             //unset homeDrive attribute for user
5369             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
5370             free(DelMods[0]);
5371         }
5372     }
5373     else
5374     {
5375         drives_v[0] = strdup(homeDrive);
5376         ADD_ATTR("homeDrive", drives_v, OpType);
5377     }
5378
5379     return(n);
5380 }
5381
5382 int GetServerList(char *ldap_domain, char **ServerList)
5383 {
5384   unsigned long   rc;
5385   int             group_count;
5386   int             UseSFU30;
5387   int             Count;
5388   int             i;
5389   int             k;
5390   int             ServerListFound;
5391   char            default_server[256];
5392   char            dn_path[256];
5393   char            *attr_array[3];
5394   char            *sPtr;
5395   char            base[128];
5396   char            filter[128];
5397   LK_ENTRY        *group_base;
5398   LK_ENTRY        *gPtr;
5399   LDAP            *ldap_handle;
5400   FILE            *fptr;
5401
5402   memset(default_server, '\0', sizeof(default_server));
5403   memset(dn_path, '\0', sizeof(dn_path));
5404   for (i = 0; i < MAX_SERVER_NAMES; i++)
5405     {
5406       if (ServerList[i] != NULL)
5407         {
5408           free(ServerList[i]);
5409           ServerList[i] = NULL;
5410         }
5411     }
5412   if (rc = ad_connect(&ldap_handle, ldap_domain, dn_path, "", "", default_server, 0, 
5413                       ServerList))
5414       return(1);
5415   memset(ServerList, '\0', sizeof(ServerList[0]) * MAX_SERVER_NAMES);
5416   group_count = 0;
5417   group_base = NULL;
5418   Count = 0;
5419   ServerListFound = 0;
5420
5421   strcpy(filter, "(&(objectClass=rIDManager)(fSMORoleOwner=*))");
5422   attr_array[0] = "fSMORoleOwner";
5423   attr_array[1] = NULL;
5424   if (!(rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5425                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
5426     {
5427       if (group_count != 0)
5428         {
5429           sPtr = strstr(group_base->value, ",CN=");
5430           if (sPtr != NULL)
5431             {
5432               sPtr += strlen(",CN=");
5433               if (ServerList[0] == NULL)
5434                   ServerList[0] = calloc(1, 256);
5435               strcpy(ServerList[0], sPtr);
5436               sPtr = strstr(ServerList[0], ",");
5437               if (sPtr != NULL)
5438                   (*sPtr) = '\0';
5439               ++Count;
5440               ServerListFound = 1;
5441             }
5442         }
5443     }
5444   linklist_free(group_base);
5445
5446   group_count = 0;
5447   group_base = NULL;
5448   attr_array[0] = "cn";
5449   attr_array[1] = NULL;
5450   strcpy(filter, "(cn=*)");
5451   sprintf(base, "cn=Servers,cn=Default-First-Site-Name,cn=Sites,cn=Configuration,%s", dn_path);
5452
5453   if (!(rc = linklist_build(ldap_handle, base, filter, attr_array, 
5454                            &group_base, &group_count, LDAP_SCOPE_ONELEVEL)) != 0)
5455     {
5456       if (group_count != 0)
5457         {
5458           gPtr = group_base;
5459           while (gPtr != NULL)
5460             {
5461               if (ServerListFound != 0)
5462                 {
5463                   if (!strcasecmp(ServerList[0], gPtr->value))
5464                     {
5465                       gPtr = gPtr->next;
5466                       continue;
5467                     }
5468                 }
5469               if (Count < MAX_SERVER_NAMES)
5470                 {
5471                   if (ServerList[Count] == NULL)
5472                       ServerList[Count] = calloc(1, 256);
5473                   strcpy(ServerList[Count], gPtr->value);
5474                   gPtr = gPtr->next;
5475                   ++Count;
5476                 }
5477             }
5478         }
5479     }
5480   linklist_free(group_base);
5481
5482   UseSFU30 = 0;
5483   group_count = 0;
5484   group_base = NULL;
5485
5486   strcpy(filter, "(cn=msSFU-30-Uid-Number)");
5487   sprintf(base, "cn=schema,cn=configuration,%s", dn_path);
5488
5489   if (!(rc = linklist_build(ldap_handle, base, filter, NULL, 
5490                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
5491     {
5492       if (group_count != 0)
5493         {
5494           UseSFU30 = 1;
5495         }
5496     }
5497   linklist_free(group_base);
5498   group_count = 0;
5499   group_base = NULL;
5500
5501   if ((fptr = fopen(WINADCFG, "w+")) != NULL)
5502     {
5503       fprintf(fptr, "%s %s\n", DOMAIN, ldap_domain);
5504       if (strlen(PrincipalName) != 0)
5505           fprintf(fptr, "%s %s\n", PRINCIPALNAME, PrincipalName);
5506       if (UseSFU30)
5507           fprintf(fptr, "%s %s\n", MSSFU, SFUTYPE);
5508       for (i = 0; i < MAX_SERVER_NAMES; i++)
5509         {
5510           if (ServerList[i] != NULL)
5511             {
5512               fprintf(fptr, "%s %s\n", SERVER, ServerList[i]);
5513             }
5514         }
5515       fclose(fptr);
5516     }
5517   ldap_unbind_s(ldap_handle);
5518
5519   for (i = 0; i < MAX_SERVER_NAMES; i++)
5520     {
5521       if (ServerList[i] != NULL)
5522         {
5523           if (ServerList[i][strlen(ServerList[i]) - 1] == '\n')
5524               ServerList[i][strlen(ServerList[i]) - 1] = '\0';
5525           strcat(ServerList[i], ".");
5526           strcat(ServerList[i], ldap_domain);
5527           for (k = 0; k < (int)strlen(ServerList[i]); k++)
5528               ServerList[i][k] = toupper(ServerList[i][k]);
5529         }
5530     }
5531
5532   return(0);
5533 }
5534
5535 int attribute_update(LDAP *ldap_handle, char *distinguished_name, 
5536                       char *attribute_value, char *attribute, char *user_name)
5537 {
5538   char      *mod_v[] = {NULL, NULL};
5539   LDAPMod   *DelMods[20];
5540   LDAPMod   *mods[20];
5541   int       n;
5542   int       i;
5543   int       rc;
5544
5545   if (strlen(attribute_value) == 0)
5546     {
5547       i = 0;
5548       DEL_ATTR(attribute, LDAP_MOD_DELETE);
5549       DelMods[i] = NULL;
5550       rc = ldap_modify_s(ldap_handle, distinguished_name, DelMods);
5551       free(DelMods[0]);
5552     }
5553     else
5554     {
5555       n = 0;
5556       mod_v[0] = attribute_value;
5557       ADD_ATTR(attribute, mod_v, LDAP_MOD_REPLACE);
5558       mods[n] = NULL;
5559       if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) != LDAP_SUCCESS)
5560         {
5561           free(mods[0]);
5562           n = 0;
5563           mod_v[0] = attribute_value;
5564           ADD_ATTR(attribute, mod_v, LDAP_MOD_ADD);
5565           mods[n] = NULL;
5566           if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) != LDAP_SUCCESS)
5567             {
5568               com_err(whoami, 0, "Unable to change the %s attribute for %s in the AD : %s",
5569                       attribute, user_name, ldap_err2string(rc));
5570             }
5571         }
5572       free(mods[0]);
5573     }
5574   return(rc);
5575 }
5576
5577 int tickets_get_k5()
5578 {
5579     char temp[128];
5580     char KinitPath[128];
5581     int  retval;
5582     int  i;
5583     static char EnvVar[128];
5584     static char EnvVar1[128];
5585
5586     strcpy(EnvVar, KRB5CCNAME);
5587     retval = putenv(EnvVar);
5588     strcpy(EnvVar1, KRBTKFILE);
5589     retval = putenv(EnvVar1);
5590
5591     for (i = 0; i < (int)strlen(PrincipalName); i++)
5592         PrincipalName[i] = tolower(PrincipalName[i]);
5593     if (strlen(PrincipalName) == 0)
5594     {
5595         strcpy(PrincipalName, PRODUCTION_PRINCIPAL);
5596         if (strcasecmp(ldap_domain, PRIMARY_DOMAIN))
5597             strcpy(PrincipalName, TEST_PRINCIPAL);
5598     }
5599
5600     memset(KinitPath, '\0',sizeof(KinitPath));
5601 #ifndef _WIN32
5602     strcpy(KinitPath, "/usr/athena/bin/");
5603 #endif
5604     sprintf(temp, "%skinit -k -t %s %s", KinitPath, KEYTABFILE, PrincipalName);
5605     retval = system(temp);
5606     if (retval)
5607         return(-1);
5608     return(0);
5609 }
5610
5611 int get_tickets()
5612 {
5613
5614     if (tickets_get_k5())
5615     {
5616         sleep(1);
5617         if (tickets_get_k5())
5618         {
5619             critical_alert("AD incremental", "%s",
5620                            "winad.incr incremental failed (unable to get kerberos tickets)");
5621             exit(1);
5622         }
5623     }
5624     return(0);
5625 }
5626
5627 int destroy_cache(void)
5628 {
5629   krb5_context          context;
5630   krb5_ccache                   cache;
5631   krb5_error_code       rc;
5632
5633   context = NULL;
5634   cache = NULL;
5635   if (!krb5_init_context(&context))
5636     {
5637       if (!krb5_cc_default(context, &cache))
5638         rc = krb5_cc_destroy(context, cache);
5639     }
5640   if (context != NULL)
5641     krb5_free_context(context);
5642   dest_tkt();
5643
5644   return(rc);
5645 }
5646
5647
5648 void StringTrim(char *StringToTrim)
5649 {
5650     char    *cPtr;
5651     char    temp[256];
5652     int     i;
5653
5654     if (strlen(StringToTrim) == 0)
5655         return;
5656
5657     cPtr = StringToTrim;
5658     while (isspace(*cPtr))
5659     {
5660         ++cPtr;
5661     }
5662     strcpy(temp, cPtr);
5663     if (strlen(temp) == 0)
5664     {
5665         strcpy(StringToTrim, temp);
5666         return;
5667     }
5668     while (1)
5669     {
5670         i = strlen(temp);
5671         if (i == 0)
5672             break;
5673         if (!isspace(temp[i-1]))
5674             break;
5675         temp[i-1] = '\0';
5676     }
5677
5678     strcpy(StringToTrim, temp);
5679     return;
5680 }
5681
5682 void ReadConfigFile()
5683 {
5684     int     Count;
5685     int     i;
5686     int     k;
5687     char    temp[256];
5688     char    temp1[256];
5689     FILE    *fptr;
5690
5691     Count = 0;
5692
5693     if ((fptr = fopen(WINADCFG, "r")) != NULL)
5694     {
5695         while (fgets(temp, sizeof(temp), fptr) != 0)
5696         {
5697             for (i = 0; i < (int)strlen(temp); i++)
5698                 temp[i] = toupper(temp[i]);
5699             if (temp[strlen(temp) - 1] == '\n')
5700                 temp[strlen(temp) - 1] = '\0';
5701             StringTrim(temp);
5702             if (strlen(temp) == 0)
5703                 continue;
5704             if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
5705             {
5706                 if (strlen(temp) > (strlen(DOMAIN)))
5707                 {
5708                     strcpy(ldap_domain, &temp[strlen(DOMAIN)]);
5709                     StringTrim(ldap_domain);
5710                 }
5711             }
5712             else if (!strncmp(temp, PRINCIPALNAME, strlen(PRINCIPALNAME)))
5713             {
5714                 if (strlen(temp) > (strlen(PRINCIPALNAME)))
5715                 {
5716                     strcpy(PrincipalName, &temp[strlen(PRINCIPALNAME)]);
5717                     StringTrim(PrincipalName);
5718                 }
5719             }
5720             else if (!strncmp(temp, SERVER, strlen(SERVER)))
5721             {
5722                 if (strlen(temp) > (strlen(SERVER)))
5723                 {
5724                     ServerList[Count] = calloc(1, 256);
5725                     strcpy(ServerList[Count], &temp[strlen(SERVER)]);
5726                     StringTrim(ServerList[Count]);
5727                     ++Count;
5728                 }
5729             }
5730             else if (!strncmp(temp, MSSFU, strlen(MSSFU)))
5731             {
5732                 if (strlen(temp) > (strlen(MSSFU)))
5733                 {
5734                     strcpy(temp1, &temp[strlen(MSSFU)]);
5735                     StringTrim(temp1);
5736                     if (!strcmp(temp1, SFUTYPE))
5737                         UseSFU30 = 1;
5738                 }
5739             }
5740             else if (!strcasecmp(temp, "NOCHANGE"))
5741             {
5742                 NoChangeConfigFile = 1;
5743             }
5744             else
5745             {
5746                 if (strlen(ldap_domain) != 0)
5747                 {
5748                     memset(ldap_domain, '\0', sizeof(ldap_domain));
5749                     break;
5750                 }
5751                 if (strlen(temp) != 0)
5752                     strcpy(ldap_domain, temp);
5753             }
5754         }
5755         fclose(fptr);
5756     }
5757
5758     if (strlen(ldap_domain) == 0)
5759     {
5760         critical_alert("incremental", "%s",
5761                        "winad.incr cannot run due to a configuration error in winad.cfg");
5762         exit(1);
5763     }
5764     if (Count == 0)
5765         return;
5766     for (i = 0; i < Count; i++)
5767     {
5768         if (ServerList[i] != 0)
5769         {
5770             strcat(ServerList[i], ".");
5771             strcat(ServerList[i], ldap_domain);
5772             for (k = 0; k < (int)strlen(ServerList[i]); k++)
5773                 ServerList[i][k] = toupper(ServerList[i][k]);
5774         }
5775     }
5776
5777 }
This page took 0.513052 seconds and 5 git commands to generate.