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