2 * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 #include <sys/sysctl.h>
28 #include <CoreFoundation/CoreFoundation.h>
29 #include <OpenDirectory/OpenDirectory.h>
30 #include <OpenDirectory/OpenDirectoryPriv.h>
32 extern char* progname
;
36 cfprintf(FILE* file
, const char* format
, ...) {
40 va_start(args
, format
);
41 CFStringRef formatStr
= CFStringCreateWithCStringNoCopy(NULL
, format
, kCFStringEncodingUTF8
, kCFAllocatorNull
);
43 CFStringRef str
= CFStringCreateWithFormatAndArguments(NULL
, NULL
, formatStr
, args
);
45 size_t size
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(str
), kCFStringEncodingUTF8
) + 1;
48 if (cstr
&& CFStringGetCString(str
, cstr
, size
, kCFStringEncodingUTF8
)) {
49 result
= fprintf(file
, "%s", cstr
);
60 show_error(CFErrorRef error
) {
62 CFStringRef desc
= CFErrorCopyDescription(error
);
64 cfprintf(stderr
, "%s: %@", progname
, desc
);
67 desc
= CFErrorCopyFailureReason(error
);
68 if (desc
) cfprintf(stderr
, " %@", desc
);
70 desc
= CFErrorCopyRecoverySuggestion(error
);
71 if (desc
) cfprintf(stderr
, " %@", desc
);
73 fprintf(stderr
, "\n");
78 od_passwd(char* uname
, char* locn
, char* aname
)
80 int change_pass_on_self
;
81 CFErrorRef error
= NULL
;
82 CFStringRef username
= NULL
;
83 CFStringRef location
= NULL
;
84 CFStringRef authname
= NULL
;
85 ODNodeRef node
= NULL
;
86 ODRecordRef rec
= NULL
;
87 CFStringRef oldpass
= NULL
;
88 CFStringRef newpass
= NULL
;
94 * If no explicit authorization name was specified (via -u)
95 * then default to the target user.
98 aname
= strdup(uname
);
101 master_mode
= (getuid() == 0);
102 change_pass_on_self
= (strcmp(aname
, uname
) == 0);
105 location
= CFStringCreateWithCString(NULL
, locn
, kCFStringEncodingUTF8
);
109 authname
= CFStringCreateWithCString(NULL
, aname
, kCFStringEncodingUTF8
);
113 username
= CFStringCreateWithCString(NULL
, uname
, kCFStringEncodingUTF8
);
114 if (!username
) return -1;
118 * Copy the record from the specified node, or perform a search.
121 node
= ODNodeCreateWithName(NULL
, kODSessionDefault
, location
, &error
);
123 node
= ODNodeCreateWithNodeType(NULL
, kODSessionDefault
, kODNodeTypeAuthentication
, &error
);
127 rec
= ODNodeCopyRecord(node
, kODRecordTypeUsers
, username
, NULL
, &error
);
135 fprintf(stderr
, "%s: Unknown user name '%s'.\n", progname
, uname
);
141 * Get the actual location.
143 CFArrayRef values
= NULL
;
144 values
= ODRecordCopyValues(rec
, kODAttributeTypeMetaNodeLocation
, &error
);
145 location
= (values
&& CFArrayGetCount(values
) > 0) ? CFArrayGetValueAtIndex(values
, 0) : location
;
147 printf("Changing password for %s.\n", uname
);
150 * Prompt for password if not super-user, or if changing a remote node.
152 int needs_auth
= (!master_mode
|| CFStringCompareWithOptions(location
, CFSTR("/Local/"), CFRangeMake(0, 7), 0) != kCFCompareEqualTo
);
156 if (change_pass_on_self
) {
157 strlcpy(prompt
, "Old password:", sizeof(prompt
));
159 snprintf(prompt
, sizeof(prompt
), "Password for %s:", aname
);
161 char *p
= getpass( prompt
);
163 oldpass
= CFStringCreateWithCString(NULL
, p
, kCFStringEncodingUTF8
);
164 memset(p
, 0, strlen(p
));
169 char *p
= getpass("New password:");
170 if (p
&& strlen(p
) > 0) {
171 newpass
= CFStringCreateWithCString(NULL
, p
, kCFStringEncodingUTF8
);
172 memset(p
, 0, strlen(p
));
174 printf("Password unchanged.\n");
178 p
= getpass("Retype new password:");
180 CFStringRef verify
= CFStringCreateWithCString(NULL
, p
, kCFStringEncodingUTF8
);
181 if (!verify
|| !CFEqual(newpass
, verify
)) {
182 if (verify
) CFRelease(verify
);
183 printf("Mismatch; try again, EOF to quit.\n");
191 ODRecordChangePassword(rec
, oldpass
, newpass
, &error
);
198 if (oldpass
) CFRelease(oldpass
);
199 if (newpass
) CFRelease(newpass
);
202 if ( status
!= eDSNoErr
) {
205 case eDSAuthPasswordTooShort
:
206 errMsgStr
= "The new password is too short.";
209 case eDSAuthPasswordTooLong
:
210 errMsgStr
= "The new password is too long.";
213 case eDSAuthPasswordNeedsLetter
:
214 errMsgStr
= "The new password must contain a letter.";
217 case eDSAuthPasswordNeedsDigit
:
218 errMsgStr
= "The new password must contain a number.";
224 fprintf(stderr
, "%s\n", errMsgStr
);