]> git.saurik.com Git - apple/system_cmds.git/blame - passwd.tproj/ds_passwd.c
system_cmds-279.1.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 *
d904471c
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,
d904471c
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
52void
c3a08f59 53ds_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
112int
113ds_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;
146
147 if (uname == NULL)
148 return -1;
149
150 loginUser = getlogin();
151 if ( loginUser != NULL )
152 changePassOnSelf = ( strcmp( loginUser, uname ) == 0 );
153
154 status = dsOpenDirService( &dsRef );
155 if (status != eDSNoErr)
156 return status;
157
158 do
159 {
160 if ( tDataBuff == NULL )
161 tDataBuff = dsDataBufferAllocate( dsRef, 4096 );
162 if (tDataBuff == NULL) break;
163
164 if ( locn != NULL )
165 {
166 nodeName = dsBuildFromPath( dsRef, locn, "/" );
167 if ( nodeName == NULL ) break;
168
169 // find
170 status = dsFindDirNodes( dsRef, tDataBuff, nodeName, eDSiExact, &nodeCount, &context );
171 }
172 else
173 {
174 // find on search node
175 status = dsFindDirNodes( dsRef, tDataBuff, NULL, eDSSearchNodeName, &nodeCount, &context );
176 }
177
178 if (status != eDSNoErr) break;
179 if ( nodeCount < 1 ) {
180 status = eDSNodeNotFound;
181 break;
182 }
183
184 if ( isroot == 1 )
185 {
186 // we already tried SetPasswordAsRoot and it didn't work
187 // get the old (current) password and try again
188
189 // getpass
190 isroot = 0;
191 wasroot = 1;
192 }
193 else
194 if ( getuid() == 0 )
195 isroot = 1;
196
c3a08f59 197 ds_getpasswd( loginUser, uname, isroot, wasroot, changePassOnSelf, &old_clear, &new_clear );
20e66415
A
198
199 status = dsGetDirNodeName( dsRef, tDataBuff, 1, &nodeName );
200 if (status != eDSNoErr) continue;
201
202 status = dsOpenDirNode( dsRef, nodeName, &nodeRef );
203 dsDataListDeallocate( dsRef, nodeName );
204 free( nodeName );
205 nodeName = NULL;
206 if (status != eDSNoErr) continue;
207
208 pRecName = dsBuildListFromStrings( dsRef, uname, NULL );
209 pRecType = dsBuildListFromStrings( dsRef, kDSStdRecordTypeUsers, NULL );
210 pAttrType = dsBuildListFromStrings( dsRef, kDSNAttrMetaNodeLocation, kDSNAttrRecordName, NULL );
211
212 recCount = 1;
213 status = dsGetRecordList( nodeRef, tDataBuff, pRecName, eDSExact, pRecType,
214 pAttrType, 0, &recCount, &context );
215 if ( status != eDSNoErr ) break;
216 if ( recCount == 0 ) {
217 status = eDSAuthUnknownUser;
218 break;
219 }
220
221 status = dsGetRecordEntry( nodeRef, tDataBuff, 1, &attrListRef, &pRecEntry );
222 if ( status != eDSNoErr ) break;
223
224 for ( attrIndex = 1; (attrIndex <= pRecEntry->fRecordAttributeCount) && (status == eDSNoErr); attrIndex++ )
225 {
226 status = dsGetAttributeEntry( nodeRef, tDataBuff, attrListRef, attrIndex, &valueRef, &pAttrEntry );
227 if ( status == eDSNoErr && pAttrEntry != NULL )
228 {
229 if ( strcmp( pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrMetaNodeLocation ) == 0 )
230 {
231 status = dsGetAttributeValue( nodeRef, tDataBuff, 1, valueRef, &pValueEntry );
232 if ( status == eDSNoErr && pValueEntry != NULL )
233 {
234 pUserLocation = (char *) calloc( pValueEntry->fAttributeValueData.fBufferLength + 1, sizeof(char) );
235 memcpy( pUserLocation, pValueEntry->fAttributeValueData.fBufferData, pValueEntry->fAttributeValueData.fBufferLength );
236 }
237 }
238 else
239 if ( strcmp( pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrRecordName ) == 0 )
240 {
241 status = dsGetAttributeValue( nodeRef, tDataBuff, 1, valueRef, &pValueEntry );
242 if ( status == eDSNoErr && pValueEntry != NULL )
243 {
244 pUserName = (char *) calloc( pValueEntry->fAttributeValueData.fBufferLength + 1, sizeof(char) );
245 memcpy( pUserName, pValueEntry->fAttributeValueData.fBufferData, pValueEntry->fAttributeValueData.fBufferLength );
246 }
247 }
248
249 if ( pValueEntry != NULL )
250 dsDeallocAttributeValueEntry( dsRef, pValueEntry );
251 pValueEntry = NULL;
252
253 dsDeallocAttributeEntry( dsRef, pAttrEntry );
254 pAttrEntry = NULL;
255 dsCloseAttributeValueList( valueRef );
256 valueRef = 0;
257 }
258 }
259
260 pUserNode = dsBuildFromPath( dsRef, pUserLocation, "/" );
261 status = dsOpenDirNode( dsRef, pUserNode, &userNodeRef );
262 if ( status != eDSNoErr ) break;
263
264 pStepBuff = dsDataBufferAllocate( dsRef, 128 );
265
266 if ( isroot )
267 {
268 pAuthType = dsDataNodeAllocateString( dsRef, kDSStdAuthSetPasswdAsRoot );
269 uiCurr = 0;
270
271 // User name
272 uiLen = strlen( pUserName );
273 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) );
274 uiCurr += sizeof( unsigned long );
275 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), pUserName, uiLen );
276 uiCurr += uiLen;
277
278 // new pw
279 uiLen = strlen( new_clear );
280 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) );
281 uiCurr += sizeof( unsigned long );
282 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), new_clear, uiLen );
283 uiCurr += uiLen;
284
285 tDataBuff->fBufferLength = uiCurr;
286
287 status = dsDoDirNodeAuth( userNodeRef, pAuthType, 1, tDataBuff, pStepBuff, NULL );
288 }
289 else
290 if ( changePassOnSelf )
291 {
292 pAuthType = dsDataNodeAllocateString( dsRef, kDSStdAuthChangePasswd );
293 uiCurr = 0;
294
295 // User name
296 uiLen = strlen( pUserName );
297 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) );
298 uiCurr += sizeof( unsigned long );
299 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), pUserName, uiLen );
300 uiCurr += uiLen;
301
302 // old pw
303 uiLen = strlen( old_clear );
304 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) );
305 uiCurr += sizeof( unsigned long );
306 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), old_clear, uiLen );
307 uiCurr += uiLen;
308
309 // new pw
310 uiLen = strlen( new_clear );
311 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) );
312 uiCurr += sizeof( unsigned long );
313 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), new_clear, uiLen );
314 uiCurr += uiLen;
315
316 tDataBuff->fBufferLength = uiCurr;
317
318 status = dsDoDirNodeAuth( userNodeRef, pAuthType, 1, tDataBuff, pStepBuff, NULL );
319 }
320 else
321 {
322 pAuthType = dsDataNodeAllocateString( dsRef, kDSStdAuthSetPasswd );
323 uiCurr = 0;
324
325 // User name
326 uiLen = strlen( pUserName );
327 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) );
328 uiCurr += sizeof( unsigned long );
329 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), pUserName, uiLen );
330 uiCurr += uiLen;
331
332 // new pw
333 uiLen = strlen( new_clear );
334 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) );
335 uiCurr += sizeof( unsigned long );
336 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), new_clear, uiLen );
337 uiCurr += uiLen;
338
339 // Authenticator name
340 uiLen = strlen( loginUser );
341 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) );
342 uiCurr += sizeof( unsigned long );
343 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), loginUser, uiLen );
344 uiCurr += uiLen;
345
346 // authenticator pw
347 uiLen = strlen( old_clear );
348 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( unsigned long ) );
349 uiCurr += sizeof( unsigned long );
350 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), old_clear, uiLen );
351 uiCurr += uiLen;
352
353 tDataBuff->fBufferLength = uiCurr;
354
355 status = dsDoDirNodeAuth( userNodeRef, pAuthType, 1, tDataBuff, pStepBuff, NULL );
356 }
357 }
358 while ( isroot == 1 && status != eDSNoErr );
359
360 /* old_clear and new_clear are statics (don't call free) */
361 if (old_clear != NULL) {
362 memset(old_clear, 0, strlen(old_clear));
363 }
364 if (new_clear != NULL) {
365 memset(new_clear, 0, strlen(new_clear));
366 }
367 if (tDataBuff != NULL) {
368 memset(tDataBuff, 0, tDataBuff->fBufferSize);
369 dsDataBufferDeAllocate( dsRef, tDataBuff );
370 tDataBuff = NULL;
371 }
372
373 if (pStepBuff != NULL) {
374 dsDataBufferDeAllocate( dsRef, pStepBuff );
375 pStepBuff = NULL;
376 }
377 if (pUserLocation != NULL ) {
378 free(pUserLocation);
379 pUserLocation = NULL;
380 }
381 if (pRecName != NULL) {
382 dsDataListDeallocate( dsRef, pRecName );
383 free( pRecName );
384 pRecName = NULL;
385 }
386 if (pRecType != NULL) {
387 dsDataListDeallocate( dsRef, pRecType );
388 free( pRecType );
389 pRecType = NULL;
390 }
391 if (pAttrType != NULL) {
392 dsDataListDeallocate( dsRef, pAttrType );
393 free( pAttrType );
394 pAttrType = NULL;
395 }
396 if (nodeRef != 0) {
397 dsCloseDirNode(nodeRef);
398 nodeRef = 0;
399 }
400 if (dsRef != 0) {
401 dsCloseDirService(dsRef);
402 dsRef = 0;
403 }
404
405 if ( status != eDSNoErr ) {
406 errno = EACCES;
407 fprintf(stderr, "Sorry\n");
408 exit(1);
409 }
410
411 return status;
412}
413
414
415
416
417
418
419
420
421
422
423