2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
27 #include <sys/param.h>
28 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32 #include <sys/ioctl.h>
38 #include <sys/dirent.h>
40 #include <DirectoryService/DirServices.h>
41 #include <DirectoryService/DirServicesConst.h>
42 #include <DirectoryService/DirServicesTypes.h>
43 #include <DirectoryService/DirServicesUtils.h>
45 // password server can store 511 characters + a terminator.
46 #define kMaxPassword 512
48 //-------------------------------------------------------------------------------------
50 //-------------------------------------------------------------------------------------
53 ds_getpasswd(const char *loginUser
, char *name
, int isroot
, int wasroot
, int changePassOnSelf
, char **old_clear
, char **new_clear
)
57 static char obuf
[kMaxPassword
];
58 static char nbuf
[kMaxPassword
];
59 char prompt
[MAXNAMLEN
+ 16];
61 printf("Changing password for %s.\n", name
);
67 if ( changePassOnSelf
)
69 strcpy( prompt
, "Old password:" );
73 snprintf( prompt
, sizeof(prompt
), "password for %s:", loginUser
);
76 p
= getpass( prompt
);
77 snprintf( obuf
, sizeof(obuf
), "%s", p
);
86 p
= getpass("New password:");
89 printf("Password unchanged.\n");
96 snprintf( nbuf
, sizeof(nbuf
), "%s", p
);
97 if (!strcmp(nbuf
, getpass("Retype new password:"))) break;
99 printf("Mismatch; try again, EOF to quit.\n");
108 //-------------------------------------------------------------------------------------
110 //-------------------------------------------------------------------------------------
113 ds_passwd(char *uname
, char *locn
)
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
;
144 char *loginUser
= NULL
;
145 int changePassOnSelf
= 1;
146 const char *errMsgStr
= NULL
;
147 struct passwd
*userRec
= NULL
;
152 /* getlogin() is the wrong thing to use here. Use getpwuid(getuid()); */
155 userRec
= getpwuid( getuid() );
156 if ( userRec
!= NULL
) {
157 loginUser
= userRec
->pw_name
;
158 if ( loginUser
!= NULL
)
159 changePassOnSelf
= (strcmp(loginUser
, uname
) == 0);
162 status
= dsOpenDirService( &dsRef
);
163 if (status
!= eDSNoErr
)
168 if ( tDataBuff
== NULL
)
169 tDataBuff
= dsDataBufferAllocate( dsRef
, 4096 );
170 if (tDataBuff
== NULL
) break;
174 nodeName
= dsBuildFromPath( dsRef
, locn
, "/" );
175 if ( nodeName
== NULL
) break;
178 status
= dsFindDirNodes( dsRef
, tDataBuff
, nodeName
, eDSiExact
, &nodeCount
, &context
);
182 // find on search node
183 status
= dsFindDirNodes( dsRef
, tDataBuff
, NULL
, eDSSearchNodeName
, &nodeCount
, &context
);
186 if (status
!= eDSNoErr
) break;
187 if ( nodeCount
< 1 ) {
188 status
= eDSNodeNotFound
;
194 // we already tried SetPasswordAsRoot and it didn't work
195 // get the old (current) password and try again
205 ds_getpasswd( loginUser
, uname
, isroot
, wasroot
, changePassOnSelf
, &old_clear
, &new_clear
);
207 status
= dsGetDirNodeName( dsRef
, tDataBuff
, 1, &nodeName
);
208 if (status
!= eDSNoErr
) continue;
210 status
= dsOpenDirNode( dsRef
, nodeName
, &nodeRef
);
211 dsDataListDeallocate( dsRef
, nodeName
);
214 if (status
!= eDSNoErr
) continue;
216 pRecName
= dsBuildListFromStrings( dsRef
, uname
, NULL
);
217 pRecType
= dsBuildListFromStrings( dsRef
, kDSStdRecordTypeUsers
, NULL
);
218 pAttrType
= dsBuildListFromStrings( dsRef
, kDSNAttrMetaNodeLocation
, kDSNAttrRecordName
, NULL
);
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
;
229 status
= dsGetRecordEntry( nodeRef
, tDataBuff
, 1, &attrListRef
, &pRecEntry
);
230 if ( status
!= eDSNoErr
) break;
232 for ( attrIndex
= 1; (attrIndex
<= pRecEntry
->fRecordAttributeCount
) && (status
== eDSNoErr
); attrIndex
++ )
234 status
= dsGetAttributeEntry( nodeRef
, tDataBuff
, attrListRef
, attrIndex
, &valueRef
, &pAttrEntry
);
235 if ( status
== eDSNoErr
&& pAttrEntry
!= NULL
)
237 if ( strcmp( pAttrEntry
->fAttributeSignature
.fBufferData
, kDSNAttrMetaNodeLocation
) == 0 )
239 status
= dsGetAttributeValue( nodeRef
, tDataBuff
, 1, valueRef
, &pValueEntry
);
240 if ( status
== eDSNoErr
&& pValueEntry
!= NULL
)
242 pUserLocation
= (char *) calloc( pValueEntry
->fAttributeValueData
.fBufferLength
+ 1, sizeof(char) );
243 memcpy( pUserLocation
, pValueEntry
->fAttributeValueData
.fBufferData
, pValueEntry
->fAttributeValueData
.fBufferLength
);
247 if ( strcmp( pAttrEntry
->fAttributeSignature
.fBufferData
, kDSNAttrRecordName
) == 0 )
249 status
= dsGetAttributeValue( nodeRef
, tDataBuff
, 1, valueRef
, &pValueEntry
);
250 if ( status
== eDSNoErr
&& pValueEntry
!= NULL
)
252 pUserName
= (char *) calloc( pValueEntry
->fAttributeValueData
.fBufferLength
+ 1, sizeof(char) );
253 memcpy( pUserName
, pValueEntry
->fAttributeValueData
.fBufferData
, pValueEntry
->fAttributeValueData
.fBufferLength
);
257 if ( pValueEntry
!= NULL
)
258 dsDeallocAttributeValueEntry( dsRef
, pValueEntry
);
261 dsDeallocAttributeEntry( dsRef
, pAttrEntry
);
263 dsCloseAttributeValueList( valueRef
);
268 if ( pUserLocation
== NULL
|| pUserName
== NULL
) {
269 status
= eDSAuthInvalidUserName
;
273 pUserNode
= dsBuildFromPath( dsRef
, pUserLocation
, "/" );
274 status
= dsOpenDirNode( dsRef
, pUserNode
, &userNodeRef
);
275 if ( status
!= eDSNoErr
) break;
277 pStepBuff
= dsDataBufferAllocate( dsRef
, 128 );
281 pAuthType
= dsDataNodeAllocateString( dsRef
, kDSStdAuthSetPasswdAsRoot
);
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
);
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
);
298 tDataBuff
->fBufferLength
= uiCurr
;
300 status
= dsDoDirNodeAuth( userNodeRef
, pAuthType
, 1, tDataBuff
, pStepBuff
, NULL
);
303 if ( changePassOnSelf
)
305 pAuthType
= dsDataNodeAllocateString( dsRef
, kDSStdAuthChangePasswd
);
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
);
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
);
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
);
329 tDataBuff
->fBufferLength
= uiCurr
;
331 status
= dsDoDirNodeAuth( userNodeRef
, pAuthType
, 1, tDataBuff
, pStepBuff
, NULL
);
334 if ( loginUser
!= NULL
)
336 pAuthType
= dsDataNodeAllocateString( dsRef
, kDSStdAuthSetPasswd
);
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
);
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
);
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
);
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
);
367 tDataBuff
->fBufferLength
= uiCurr
;
369 status
= dsDoDirNodeAuth( userNodeRef
, pAuthType
, 1, tDataBuff
, pStepBuff
, NULL
);
373 status
= eDSAuthFailed
;
376 while ( isroot
== 1 && status
!= eDSNoErr
);
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
));
382 if (new_clear
!= NULL
) {
383 memset(new_clear
, 0, strlen(new_clear
));
385 if (tDataBuff
!= NULL
) {
386 memset(tDataBuff
, 0, tDataBuff
->fBufferSize
);
387 dsDataBufferDeAllocate( dsRef
, tDataBuff
);
391 if (pStepBuff
!= NULL
) {
392 dsDataBufferDeAllocate( dsRef
, pStepBuff
);
395 if (pUserLocation
!= NULL
) {
397 pUserLocation
= NULL
;
399 if (pRecName
!= NULL
) {
400 dsDataListDeallocate( dsRef
, pRecName
);
404 if (pRecType
!= NULL
) {
405 dsDataListDeallocate( dsRef
, pRecType
);
409 if (pAttrType
!= NULL
) {
410 dsDataListDeallocate( dsRef
, pAttrType
);
415 dsCloseDirNode(nodeRef
);
419 dsCloseDirService(dsRef
);
423 if ( status
!= eDSNoErr
) {
427 case eDSAuthPasswordTooShort
:
428 errMsgStr
= "The new password is too short.";
431 case eDSAuthPasswordTooLong
:
432 errMsgStr
= "The new password is too long.";
435 case eDSAuthPasswordNeedsLetter
:
436 errMsgStr
= "The new password must contain a letter.";
439 case eDSAuthPasswordNeedsDigit
:
440 errMsgStr
= "The new password must contain a number.";
446 fprintf(stderr
, "%s\n", errMsgStr
);