]>
Commit | Line | Data |
---|---|---|
20e66415 A |
1 | /* |
2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
2fc1e207 A |
6 | * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights |
7 | * Reserved. This file contains Original Code and/or Modifications of | |
8 | * Original Code as defined in and that are subject to the Apple Public | |
9 | * Source License Version 1.0 (the 'License'). You may not use this file | |
10 | * except in compliance with the License. Please obtain a copy of the | |
11 | * License at http://www.apple.com/publicsource and read it before using | |
12 | * this file. | |
20e66415 A |
13 | * |
14 | * The Original Code and all software distributed under the License are | |
15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
2fc1e207 A |
18 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the |
19 | * License for the specific language governing rights and limitations | |
20 | * under the License." | |
20e66415 A |
21 | * |
22 | * @APPLE_LICENSE_HEADER_END@ | |
23 | */ | |
24 | #include <stdio.h> | |
25 | #include <unistd.h> | |
26 | #include <stdlib.h> | |
27 | #include <sys/param.h> | |
28 | #include <sys/socket.h> | |
29 | #include <net/if.h> | |
30 | #include <netinet/in.h> | |
31 | #include <arpa/inet.h> | |
32 | #include <sys/ioctl.h> | |
33 | #include <errno.h> | |
34 | #include <pwd.h> | |
35 | #include <netdb.h> | |
36 | #include <ctype.h> | |
37 | #include <string.h> | |
c3a08f59 | 38 | #include <sys/dirent.h> |
20e66415 A |
39 | |
40 | #include <DirectoryService/DirServices.h> | |
41 | #include <DirectoryService/DirServicesConst.h> | |
42 | #include <DirectoryService/DirServicesTypes.h> | |
43 | #include <DirectoryService/DirServicesUtils.h> | |
44 | ||
45 | // password server can store 511 characters + a terminator. | |
46 | #define kMaxPassword 512 | |
47 | ||
48 | //------------------------------------------------------------------------------------- | |
49 | // ds_getpasswd | |
50 | //------------------------------------------------------------------------------------- | |
51 | ||
52 | void | |
c3a08f59 | 53 | ds_getpasswd(const char *loginUser, char *name, int isroot, int wasroot, int changePassOnSelf, char **old_clear, char **new_clear) |
20e66415 A |
54 | { |
55 | int tries, len; | |
56 | char *p; | |
57 | static char obuf[kMaxPassword]; | |
58 | static char nbuf[kMaxPassword]; | |
c3a08f59 | 59 | char prompt[MAXNAMLEN + 16]; |
20e66415 A |
60 | |
61 | printf("Changing password for %s.\n", name); | |
62 | ||
63 | p = ""; | |
64 | ||
65 | if (isroot == 0) | |
66 | { | |
c3a08f59 A |
67 | if ( changePassOnSelf ) |
68 | { | |
69 | strcpy( prompt, "Old password:" ); | |
70 | } | |
71 | else | |
72 | { | |
73 | snprintf( prompt, sizeof(prompt), "password for %s:", loginUser ); | |
74 | } | |
75 | ||
76 | p = getpass( prompt ); | |
20e66415 A |
77 | snprintf( obuf, sizeof(obuf), "%s", p ); |
78 | } | |
79 | ||
80 | if ( wasroot == 0 ) | |
81 | { | |
82 | tries = 0; | |
83 | nbuf[0] = '\0'; | |
84 | for (;;) | |
85 | { | |
86 | p = getpass("New password:"); | |
87 | if (!*p) | |
88 | { | |
89 | printf("Password unchanged.\n"); | |
90 | exit(0); | |
91 | } | |
92 | ||
93 | tries++; | |
94 | len = strlen(p); | |
95 | ||
96 | snprintf( nbuf, sizeof(nbuf), "%s", p ); | |
97 | if (!strcmp(nbuf, getpass("Retype new password:"))) break; | |
98 | ||
99 | printf("Mismatch; try again, EOF to quit.\n"); | |
100 | } | |
101 | } | |
102 | ||
103 | *old_clear = obuf; | |
104 | *new_clear = nbuf; | |
105 | } | |
106 | ||
107 | ||
108 | //------------------------------------------------------------------------------------- | |
109 | // ds_passwd | |
110 | //------------------------------------------------------------------------------------- | |
111 | ||
112 | int | |
113 | ds_passwd(char *uname, char *locn) | |
114 | { | |
115 | tDirReference dsRef = 0; | |
116 | tDataBuffer *tDataBuff = NULL; | |
117 | tDirNodeReference nodeRef = 0; | |
118 | long status = eDSNoErr; | |
119 | tContextData context = NULL; | |
120 | unsigned long nodeCount = 0; | |
121 | unsigned long attrIndex = 0; | |
122 | tDataList *nodeName = NULL; | |
123 | tAttributeEntryPtr pAttrEntry = NULL; | |
124 | tDataList *pRecName = NULL; | |
125 | tDataList *pRecType = NULL; | |
126 | tDataList *pAttrType = NULL; | |
127 | unsigned long recCount = 0; | |
128 | tRecordEntry *pRecEntry = NULL; | |
129 | tAttributeListRef attrListRef = 0; | |
130 | char *pUserLocation = NULL; | |
131 | char *pUserName = NULL; | |
132 | tAttributeValueListRef valueRef = 0; | |
133 | tAttributeValueEntry *pValueEntry = NULL; | |
134 | tDataList *pUserNode = NULL; | |
135 | tDirNodeReference userNodeRef = 0; | |
136 | tDataBuffer *pStepBuff = NULL; | |
137 | tDataNode *pAuthType = NULL; | |
138 | unsigned long uiCurr = 0; | |
139 | unsigned long uiLen = 0; | |
140 | char *old_clear = NULL; | |
141 | char *new_clear = NULL; | |
142 | int isroot = 0; | |
143 | int wasroot = 0; | |
144 | char *loginUser = NULL; | |
145 | int changePassOnSelf = 1; | |
2fc1e207 A |
146 | const char *errMsgStr = NULL; |
147 | struct passwd *userRec = NULL; | |
20e66415 A |
148 | |
149 | if (uname == NULL) | |
150 | return -1; | |
151 | ||
2fc1e207 A |
152 | /* getlogin() is the wrong thing to use here. Use getpwuid(getuid()); */ |
153 | /* sns 5 Jan 2005 */ | |
154 | ||
155 | userRec = getpwuid( getuid() ); | |
156 | if ( userRec != NULL ) { | |
157 | loginUser = userRec->pw_name; | |
158 | if ( loginUser != NULL ) | |
159 | changePassOnSelf = (strcmp(loginUser, uname) == 0); | |
160 | } | |
20e66415 A |
161 | |
162 | status = dsOpenDirService( &dsRef ); | |
163 | if (status != eDSNoErr) | |
164 | return status; | |
165 | ||
166 | do | |
167 | { | |
168 | if ( tDataBuff == NULL ) | |
169 | tDataBuff = dsDataBufferAllocate( dsRef, 4096 ); | |
170 | if (tDataBuff == NULL) break; | |
171 | ||
172 | if ( locn != NULL ) | |
173 | { | |
174 | nodeName = dsBuildFromPath( dsRef, locn, "/" ); | |
175 | if ( nodeName == NULL ) break; | |
176 | ||
177 | // find | |
178 | status = dsFindDirNodes( dsRef, tDataBuff, nodeName, eDSiExact, &nodeCount, &context ); | |
179 | } | |
180 | else | |
181 | { | |
182 | // find on search node | |
183 | status = dsFindDirNodes( dsRef, tDataBuff, NULL, eDSSearchNodeName, &nodeCount, &context ); | |
184 | } | |
185 | ||
186 | if (status != eDSNoErr) break; | |
187 | if ( nodeCount < 1 ) { | |
188 | status = eDSNodeNotFound; | |
189 | break; | |
190 | } | |
191 | ||
192 | if ( isroot == 1 ) | |
193 | { | |
194 | // we already tried SetPasswordAsRoot and it didn't work | |
195 | // get the old (current) password and try again | |
196 | ||
197 | // getpass | |
198 | isroot = 0; | |
199 | wasroot = 1; | |
200 | } | |
201 | else | |
202 | if ( getuid() == 0 ) | |
203 | isroot = 1; | |
204 | ||
c3a08f59 | 205 | ds_getpasswd( loginUser, uname, isroot, wasroot, changePassOnSelf, &old_clear, &new_clear ); |
20e66415 A |
206 | |
207 | status = dsGetDirNodeName( dsRef, tDataBuff, 1, &nodeName ); | |
208 | if (status != eDSNoErr) continue; | |
209 | ||
210 | status = dsOpenDirNode( dsRef, nodeName, &nodeRef ); | |
211 | dsDataListDeallocate( dsRef, nodeName ); | |
212 | free( nodeName ); | |
213 | nodeName = NULL; | |
214 | if (status != eDSNoErr) continue; | |
215 | ||
216 | pRecName = dsBuildListFromStrings( dsRef, uname, NULL ); | |
217 | pRecType = dsBuildListFromStrings( dsRef, kDSStdRecordTypeUsers, NULL ); | |
218 | pAttrType = dsBuildListFromStrings( dsRef, kDSNAttrMetaNodeLocation, kDSNAttrRecordName, NULL ); | |
219 | ||
220 | recCount = 1; | |
221 | status = dsGetRecordList( nodeRef, tDataBuff, pRecName, eDSExact, pRecType, | |
222 | pAttrType, 0, &recCount, &context ); | |
223 | if ( status != eDSNoErr ) break; | |
224 | if ( recCount == 0 ) { | |
225 | status = eDSAuthUnknownUser; | |
226 | break; | |
227 | } | |
228 | ||
229 | status = dsGetRecordEntry( nodeRef, tDataBuff, 1, &attrListRef, &pRecEntry ); | |
230 | if ( status != eDSNoErr ) break; | |
231 | ||
232 | for ( attrIndex = 1; (attrIndex <= pRecEntry->fRecordAttributeCount) && (status == eDSNoErr); attrIndex++ ) | |
233 | { | |
234 | status = dsGetAttributeEntry( nodeRef, tDataBuff, attrListRef, attrIndex, &valueRef, &pAttrEntry ); | |
235 | if ( status == eDSNoErr && pAttrEntry != NULL ) | |
236 | { | |
237 | if ( strcmp( pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrMetaNodeLocation ) == 0 ) | |
238 | { | |
239 | status = dsGetAttributeValue( nodeRef, tDataBuff, 1, valueRef, &pValueEntry ); | |
240 | if ( status == eDSNoErr && pValueEntry != NULL ) | |
241 | { | |
242 | pUserLocation = (char *) calloc( pValueEntry->fAttributeValueData.fBufferLength + 1, sizeof(char) ); | |
243 | memcpy( pUserLocation, pValueEntry->fAttributeValueData.fBufferData, pValueEntry->fAttributeValueData.fBufferLength ); | |
244 | } | |
245 | } | |
246 | else | |
247 | if ( strcmp( pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrRecordName ) == 0 ) | |
248 | { | |
249 | status = dsGetAttributeValue( nodeRef, tDataBuff, 1, valueRef, &pValueEntry ); | |
250 | if ( status == eDSNoErr && pValueEntry != NULL ) | |
251 | { | |
252 | pUserName = (char *) calloc( pValueEntry->fAttributeValueData.fBufferLength + 1, sizeof(char) ); | |
253 | memcpy( pUserName, pValueEntry->fAttributeValueData.fBufferData, pValueEntry->fAttributeValueData.fBufferLength ); | |
254 | } | |
255 | } | |
256 | ||
257 | if ( pValueEntry != NULL ) | |
258 | dsDeallocAttributeValueEntry( dsRef, pValueEntry ); | |
259 | pValueEntry = NULL; | |
260 | ||
261 | dsDeallocAttributeEntry( dsRef, pAttrEntry ); | |
262 | pAttrEntry = NULL; | |
263 | dsCloseAttributeValueList( valueRef ); | |
264 | valueRef = 0; | |
265 | } | |
266 | } | |
267 | ||
2fc1e207 A |
268 | if ( pUserLocation == NULL || pUserName == NULL ) { |
269 | status = eDSAuthInvalidUserName; | |
270 | break; | |
271 | } | |
272 | ||
20e66415 A |
273 | pUserNode = dsBuildFromPath( dsRef, pUserLocation, "/" ); |
274 | status = dsOpenDirNode( dsRef, pUserNode, &userNodeRef ); | |
275 | if ( status != eDSNoErr ) break; | |
276 | ||
277 | pStepBuff = dsDataBufferAllocate( dsRef, 128 ); | |
278 | ||
279 | if ( isroot ) | |
280 | { | |
281 | pAuthType = dsDataNodeAllocateString( dsRef, kDSStdAuthSetPasswdAsRoot ); | |
282 | uiCurr = 0; | |
283 | ||
284 | // User name | |
285 | uiLen = strlen( pUserName ); | |
286 | memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) ); | |
287 | uiCurr += sizeof( unsigned long ); | |
288 | memcpy( &(tDataBuff->fBufferData[ uiCurr ]), pUserName, uiLen ); | |
289 | uiCurr += uiLen; | |
290 | ||
291 | // new pw | |
292 | uiLen = strlen( new_clear ); | |
293 | memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) ); | |
294 | uiCurr += sizeof( unsigned long ); | |
295 | memcpy( &(tDataBuff->fBufferData[ uiCurr ]), new_clear, uiLen ); | |
296 | uiCurr += uiLen; | |
297 | ||
298 | tDataBuff->fBufferLength = uiCurr; | |
299 | ||
300 | status = dsDoDirNodeAuth( userNodeRef, pAuthType, 1, tDataBuff, pStepBuff, NULL ); | |
301 | } | |
302 | else | |
303 | if ( changePassOnSelf ) | |
304 | { | |
305 | pAuthType = dsDataNodeAllocateString( dsRef, kDSStdAuthChangePasswd ); | |
306 | uiCurr = 0; | |
307 | ||
308 | // User name | |
309 | uiLen = strlen( pUserName ); | |
310 | memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) ); | |
311 | uiCurr += sizeof( unsigned long ); | |
312 | memcpy( &(tDataBuff->fBufferData[ uiCurr ]), pUserName, uiLen ); | |
313 | uiCurr += uiLen; | |
314 | ||
315 | // old pw | |
316 | uiLen = strlen( old_clear ); | |
317 | memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) ); | |
318 | uiCurr += sizeof( unsigned long ); | |
319 | memcpy( &(tDataBuff->fBufferData[ uiCurr ]), old_clear, uiLen ); | |
320 | uiCurr += uiLen; | |
321 | ||
322 | // new pw | |
323 | uiLen = strlen( new_clear ); | |
324 | memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) ); | |
325 | uiCurr += sizeof( unsigned long ); | |
326 | memcpy( &(tDataBuff->fBufferData[ uiCurr ]), new_clear, uiLen ); | |
327 | uiCurr += uiLen; | |
328 | ||
329 | tDataBuff->fBufferLength = uiCurr; | |
330 | ||
331 | status = dsDoDirNodeAuth( userNodeRef, pAuthType, 1, tDataBuff, pStepBuff, NULL ); | |
332 | } | |
333 | else | |
2fc1e207 | 334 | if ( loginUser != NULL ) |
20e66415 A |
335 | { |
336 | pAuthType = dsDataNodeAllocateString( dsRef, kDSStdAuthSetPasswd ); | |
337 | uiCurr = 0; | |
338 | ||
339 | // User name | |
340 | uiLen = strlen( pUserName ); | |
341 | memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) ); | |
342 | uiCurr += sizeof( unsigned long ); | |
343 | memcpy( &(tDataBuff->fBufferData[ uiCurr ]), pUserName, uiLen ); | |
344 | uiCurr += uiLen; | |
345 | ||
346 | // new pw | |
347 | uiLen = strlen( new_clear ); | |
348 | memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) ); | |
349 | uiCurr += sizeof( unsigned long ); | |
350 | memcpy( &(tDataBuff->fBufferData[ uiCurr ]), new_clear, uiLen ); | |
351 | uiCurr += uiLen; | |
352 | ||
353 | // Authenticator name | |
354 | uiLen = strlen( loginUser ); | |
355 | memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) ); | |
356 | uiCurr += sizeof( unsigned long ); | |
357 | memcpy( &(tDataBuff->fBufferData[ uiCurr ]), loginUser, uiLen ); | |
358 | uiCurr += uiLen; | |
359 | ||
360 | // authenticator pw | |
361 | uiLen = strlen( old_clear ); | |
362 | memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) ); | |
363 | uiCurr += sizeof( unsigned long ); | |
364 | memcpy( &(tDataBuff->fBufferData[ uiCurr ]), old_clear, uiLen ); | |
365 | uiCurr += uiLen; | |
366 | ||
367 | tDataBuff->fBufferLength = uiCurr; | |
368 | ||
369 | status = dsDoDirNodeAuth( userNodeRef, pAuthType, 1, tDataBuff, pStepBuff, NULL ); | |
370 | } | |
2fc1e207 A |
371 | else |
372 | { | |
373 | status = eDSAuthFailed; | |
374 | } | |
20e66415 A |
375 | } |
376 | while ( isroot == 1 && status != eDSNoErr ); | |
377 | ||
378 | /* old_clear and new_clear are statics (don't call free) */ | |
379 | if (old_clear != NULL) { | |
380 | memset(old_clear, 0, strlen(old_clear)); | |
381 | } | |
382 | if (new_clear != NULL) { | |
383 | memset(new_clear, 0, strlen(new_clear)); | |
384 | } | |
385 | if (tDataBuff != NULL) { | |
386 | memset(tDataBuff, 0, tDataBuff->fBufferSize); | |
387 | dsDataBufferDeAllocate( dsRef, tDataBuff ); | |
388 | tDataBuff = NULL; | |
389 | } | |
390 | ||
391 | if (pStepBuff != NULL) { | |
392 | dsDataBufferDeAllocate( dsRef, pStepBuff ); | |
393 | pStepBuff = NULL; | |
394 | } | |
395 | if (pUserLocation != NULL ) { | |
396 | free(pUserLocation); | |
397 | pUserLocation = NULL; | |
398 | } | |
399 | if (pRecName != NULL) { | |
400 | dsDataListDeallocate( dsRef, pRecName ); | |
401 | free( pRecName ); | |
402 | pRecName = NULL; | |
403 | } | |
404 | if (pRecType != NULL) { | |
405 | dsDataListDeallocate( dsRef, pRecType ); | |
406 | free( pRecType ); | |
407 | pRecType = NULL; | |
408 | } | |
409 | if (pAttrType != NULL) { | |
410 | dsDataListDeallocate( dsRef, pAttrType ); | |
411 | free( pAttrType ); | |
412 | pAttrType = NULL; | |
413 | } | |
414 | if (nodeRef != 0) { | |
415 | dsCloseDirNode(nodeRef); | |
416 | nodeRef = 0; | |
417 | } | |
418 | if (dsRef != 0) { | |
419 | dsCloseDirService(dsRef); | |
420 | dsRef = 0; | |
421 | } | |
422 | ||
423 | if ( status != eDSNoErr ) { | |
424 | errno = EACCES; | |
2fc1e207 A |
425 | switch( status ) |
426 | { | |
427 | case eDSAuthPasswordTooShort: | |
428 | errMsgStr = "The new password is too short."; | |
429 | break; | |
430 | ||
431 | case eDSAuthPasswordTooLong: | |
432 | errMsgStr = "The new password is too long."; | |
433 | break; | |
434 | ||
435 | case eDSAuthPasswordNeedsLetter: | |
436 | errMsgStr = "The new password must contain a letter."; | |
437 | break; | |
438 | ||
439 | case eDSAuthPasswordNeedsDigit: | |
440 | errMsgStr = "The new password must contain a number."; | |
441 | break; | |
442 | ||
443 | default: | |
444 | errMsgStr = "Sorry"; | |
445 | } | |
446 | fprintf(stderr, "%s\n", errMsgStr); | |
20e66415 A |
447 | exit(1); |
448 | } | |
449 | ||
450 | return status; | |
451 | } | |
452 | ||
453 | ||
454 | ||
455 | ||
456 | ||
457 | ||
458 | ||
459 | ||
460 | ||
461 | ||
462 |