]> git.saurik.com Git - apple/system_cmds.git/blobdiff - passwd.tproj/od_passwd.c
system_cmds-805.200.21.tar.gz
[apple/system_cmds.git] / passwd.tproj / od_passwd.c
index fb4494cf9079f73092b41af331f4e1f96d939ec8..f24883a9bcc1266ea779f225b46a3045cf51919a 100644 (file)
@@ -1,15 +1,15 @@
 /*
- * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2016 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * compliance with the License. Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this
  * file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -17,7 +17,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_LICENSE_HEADER_END@
  */
 #include <stdio.h>
 #include <pwd.h>
 #include <sys/sysctl.h>
 
+#include "passwd.h"
+
+#ifdef INFO_OPEN_DIRECTORY
+
 #include <CoreFoundation/CoreFoundation.h>
 #include <OpenDirectory/OpenDirectory.h>
 #include <OpenDirectory/OpenDirectoryPriv.h>
-#include <DirectoryService/DirServicesTypes.h>
 
 extern char* progname;
 int master_mode;
@@ -67,69 +70,27 @@ show_error(CFErrorRef error) {
                }
                desc = CFErrorCopyFailureReason(error);
                if (desc) cfprintf(stderr, "  %@", desc);
-               
+
                desc = CFErrorCopyRecoverySuggestion(error);
                if (desc) cfprintf(stderr, "  %@", desc);
-               
-               fprintf(stderr, "\n");
-       }
-}
 
-static int
-is_singleuser(void) {
-       uint32_t su = 0;
-       size_t susz = sizeof(su);
-       if (sysctlbyname("kern.singleuser", &su, &susz, NULL, 0) != 0) {
-               return 0;
-       } else {
-               return (int)su;
-       }
-}
-
-static int
-load_DirectoryServicesLocal() {
-       const char* launchctl = "/bin/launchctl";
-       const char* plist = "/System/Library/LaunchDaemons/com.apple.DirectoryServicesLocal.plist";
-
-       pid_t pid = fork();
-       int status, res;
-       switch (pid) {
-               case -1: // ERROR
-                       perror("launchctl");
-                       return 0;
-               case 0: // CHILD
-                       execl(launchctl, launchctl, "load", plist, NULL);
-                       /* NOT REACHED */
-                       perror("launchctl");
-                       exit(1);
-                       break;
-               default: // PARENT
-                       do {
-                               res = waitpid(pid, &status, 0);
-                       } while (res == -1 && errno == EINTR);
-                       if (res == -1) {
-                               perror("launchctl");
-                               return 0;
-                       }
-                       break;
+               fprintf(stderr, "\n");
        }
-       return (WIFEXITED(status) && (WEXITSTATUS(status) == EXIT_SUCCESS));
 }
 
 int
 od_passwd(char* uname, char* locn, char* aname)
 {
-       int                     change_pass_on_self;
-       CFErrorRef      error = NULL;
+       int change_pass_on_self;
+       CFErrorRef error = NULL;
        CFStringRef username = NULL;
        CFStringRef location = NULL;
        CFStringRef authname = NULL;
-       ODSessionRef    session = NULL;
-       ODNodeRef       node = NULL;
+       ODNodeRef node = NULL;
        ODRecordRef rec = NULL;
        CFStringRef oldpass = NULL;
        CFStringRef newpass = NULL;
-       
+
        if (uname == NULL)
                return -1;
 
@@ -141,7 +102,7 @@ od_passwd(char* uname, char* locn, char* aname)
                aname = strdup(uname);
        }
 
-       master_mode = (getuid() == 0);
+       master_mode = (geteuid() == 0);
        change_pass_on_self = (strcmp(aname, uname) == 0);
 
        if (locn) {
@@ -157,46 +118,17 @@ od_passwd(char* uname, char* locn, char* aname)
                if (!username) return -1;
        }
 
-       /*
-        * Connect to DS server
-        */
-       session = ODSessionCreate(NULL, NULL, &error);
-       if ( !session && error && CFErrorGetCode(error) == eServerNotRunning ) {
-               /*
-                * In single-user mode, attempt to load the local DS daemon.
-                */
-               if (is_singleuser() && load_DirectoryServicesLocal()) {
-                       CFTypeRef keys[] = { kODSessionLocalPath };
-                       CFTypeRef vals[] = { CFSTR("/var/db/dslocal") };
-                       CFDictionaryRef opts = CFDictionaryCreate(NULL, keys, vals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-                       if (opts) {
-                               session = ODSessionCreate(NULL, opts, &error);
-                               CFRelease(opts);
-                       }
-
-                       if (!location) {
-                               location = CFRetain(CFSTR("/Local/Default"));
-                       }
-               } else {
-                       show_error(error);
-                       return -1;
-               }
-       }
-
-
        /*
         * Copy the record from the specified node, or perform a search.
         */
        if (location) {
-               node = ODNodeCreateWithName(NULL, session, location, &error);
+               node = ODNodeCreateWithName(NULL, kODSessionDefault, location, &error);
        } else {
-               node = ODNodeCreateWithNodeType(NULL, session, kODTypeAuthenticationSearchNode, &error);
+               node = ODNodeCreateWithNodeType(NULL, kODSessionDefault, kODNodeTypeAuthentication, &error);
        }
 
-       if (session) CFRelease(session);
-
        if (node) {
-               rec = ODNodeCopyRecord(node, CFSTR(kDSStdRecordTypeUsers), username, NULL, &error );
+               rec = ODNodeCopyRecord(node, kODRecordTypeUsers, username, NULL, &error );
                CFRelease(node);
        }
 
@@ -213,15 +145,25 @@ od_passwd(char* uname, char* locn, char* aname)
         * Get the actual location.
         */
        CFArrayRef values = NULL;
-       values = ODRecordCopyValues(rec, CFSTR(kDSNAttrMetaNodeLocation), &error);
+       values = ODRecordCopyValues(rec, kODAttributeTypeMetaNodeLocation, &error);
        location = (values && CFArrayGetCount(values) > 0) ? CFArrayGetValueAtIndex(values, 0) : location;
-       
+
        printf("Changing password for %s.\n", uname);
 
+       bool isSecureToken = false;
+       if (master_mode) {
+               CFArrayRef authorityValues = NULL;
+               authorityValues = ODRecordCopyValues(rec, kODAttributeTypeAuthenticationAuthority, &error);
+               if (authorityValues != NULL) {
+                       isSecureToken = CFArrayContainsValue(authorityValues, CFRangeMake(0, CFArrayGetCount(authorityValues)), (const void *)CFSTR(";SecureToken;"));
+                       CFRelease(authorityValues);
+               }
+       }
+
        /*
-        * Prompt for password if not super-user, or if changing a remote node.
+        * Prompt for password if not super-user, or if changing a remote node, or if changing a record that uses SecureToken.
         */
-       int needs_auth = (!master_mode || CFStringCompareWithOptions(location, CFSTR("/Local/"), CFRangeMake(0, 7), 0) != kCFCompareEqualTo);
+       int needs_auth = (!master_mode || CFStringCompareWithOptions(location, CFSTR("/Local/"), CFRangeMake(0, 7), 0) != kCFCompareEqualTo || isSecureToken);
 
        if (needs_auth) {
                char prompt[BUFSIZ];
@@ -234,6 +176,15 @@ od_passwd(char* uname, char* locn, char* aname)
                if (p) {
                        oldpass = CFStringCreateWithCString(NULL, p, kCFStringEncodingUTF8);
                        memset(p, 0, strlen(p));
+
+                       if (!change_pass_on_self) {
+                               if (!ODRecordSetNodeCredentials(rec, authname, oldpass, &error)) {
+                                       show_error(error);
+                                       exit(1);
+                               }
+                               CFRelease(oldpass);
+                               oldpass = NULL;
+                       }
                }
        }
 
@@ -246,7 +197,7 @@ od_passwd(char* uname, char* locn, char* aname)
                        printf("Password unchanged.\n");
                        exit(0);
                }
-               
+
                p = getpass("Retype new password:");
                if (p) {
                        CFStringRef verify = CFStringCreateWithCString(NULL, p, kCFStringEncodingUTF8);
@@ -260,22 +211,7 @@ od_passwd(char* uname, char* locn, char* aname)
                }
        }
 
-       if (needs_auth) {
-               CFTypeRef       values[] = { username, newpass, authname, oldpass };
-               CFArrayRef      authItems = CFArrayCreate(NULL, values, 4, &kCFTypeArrayCallBacks);
-
-               ODRecordSetNodeCredentialsExtended(rec,
-                       CFSTR(kDSStdRecordTypeUsers),
-                       CFSTR(kDSStdAuthSetPasswd),
-                       authItems,
-                       NULL,
-                       NULL,
-                       &error);
-
-               CFRelease(authItems);
-       } else {
-               ODRecordChangePassword(rec, oldpass, newpass, &error);
-       }
+       ODRecordChangePassword(rec, oldpass, newpass, &error);
 
        if (error) {
                show_error(error);
@@ -292,19 +228,19 @@ od_passwd(char* uname, char* locn, char* aname)
                        case eDSAuthPasswordTooShort:
                                errMsgStr = "The new password is too short.";
                                break;
-                       
+
                        case eDSAuthPasswordTooLong:
                                errMsgStr = "The new password is too long.";
                                break;
-                               
+
                        case eDSAuthPasswordNeedsLetter:
                                errMsgStr = "The new password must contain a letter.";
                                break;
-                               
+
                        case eDSAuthPasswordNeedsDigit:
                                errMsgStr = "The new password must contain a number.";
                                break;
-                               
+
                        default:
                                errMsgStr = "Sorry";
                }
@@ -313,3 +249,5 @@ od_passwd(char* uname, char* locn, char* aname)
 #endif
        return 0;
 }
+
+#endif /* INFO_OPEN_DIRECTORY */