1/* 2 * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 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 11 * file. 12 * 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. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 * 23 * create_fv_user.c 24 */ 25 26#include "create_fv_user.h" 27 28#include "readline.h" 29#include "tokenadmin.h" 30#include "TokenIDHelper.h" 31 32#include <stdio.h> 33#include <stdlib.h> 34#include <string.h> 35#include <unistd.h> 36#include <Security/SecKeychain.h> 37#include <SecurityFoundation/FileVaultPriv.h> 38#include <SecurityFoundation/SFAuthorization.h> 39#import <Foundation/NSString.h> 40#import <Foundation/NSDictionary.h> 41 42#if 0 43#import <Admin/LoginPrefs.h> 44#import <Admin/User.h> 45#import <Admin/UserAdditions.h> 46#import <Admin/AdminConst.h> 47#import <Admin/Group.h> 48#import <Admin/Authenticator.h> 49#import <Admin/DSAuthenticator.h> 50#else 51#import <SystemAdministration/SystemAdministration.h> 52#endif 53 54static int do_create_fv_user(const char *userShortName, const char *userFullName, const char *kcpassword); 55static BOOL verify_userFullName(const char *userFullName); 56static BOOL verify_userUnixName(const char *userShortName); 57static BOOL checkHomedirExistence(); 58static void _createUserAccount(NSArray *inCertificates); 59static BOOL authorize_me(); 60 61NSString *mNewUserFullName; 62NSString *mNewUserName; 63NSString *mNewUserNameWarn; 64NSString *mNewUserPassword; 65 66// Fix build failure. Remove this when 67// <rdar://problem/4874550> Admin support functions for creation of token protected FileVault users 68// is submitted 69#ifndef kHomeDirectoryCertificates 70#define kHomeDirectoryCertificates @"HomeDirectoryCertificates" 71#endif 72 73SFAuthorization *mAuthorization; 74/* 75 -p optional-keychain-password 76 -u usershortname 77 -l user-long-name 78 -h hash-of-encryption-key 79*/ 80 81int 82create_fv_user(int argc, char * const *argv) 83{ 84 char *userShortName = NULL; 85 char *userFullName = NULL; 86 char *kcpassword = NULL; 87 char *encryptionHash = NULL; 88 int ch, result = 0; 89 while ((ch = getopt(argc, argv, "u:l:p:h:")) != -1) 90 { 91 switch (ch) 92 { 93 case 'u': 94 userShortName = optarg; 95 break; 96 case 'l': 97 userFullName = optarg; 98 break; 99 case 'p': 100 kcpassword = optarg; 101 break; 102 case 'h': 103 encryptionHash = optarg; 104 break; 105 case '?': 106 default: 107 return 2; /* @@@ Return 2 triggers usage message. */ 108 } 109 } 110 argc -= optind; 111 argv += optind; 112 113 if (argc != 0) 114 return 2; 115 116 result = do_create_fv_user(userShortName, userFullName, kcpassword); 117 118 return result; 119} 120 121static int do_create_fv_user(const char *userShortName, const char *userFullName, const char *kcpassword) 122{ 123 OSStatus status; 124 CFTypeRef identityOrArray = NULL; 125 CFArrayRef wrappingCertificates = NULL; 126 127 if (!authorize_me()) 128 return 1; 129 130 printf("Connecting to writeconfig...\n"); 131 AdminAuthenticator *sharedAuthenticator = [AdminAuthenticator sharedAuthenticator]; 132 [sharedAuthenticator authenticateUsingAuthorization:mAuthorization]; 133 if (![sharedAuthenticator isAuthenticated]) 134 { 135 sec_error("Unable to connect to ToolLiason"); 136 return 1; 137 } 138 printf("Connected\n"); 139 140 if (!SecFileVaultMasterPasswordEnabled(NULL)) 141 { 142 sec_error("FileVault master password not enabled"); 143 return 1; 144 } 145 146 if (!verify_userFullName(userFullName)) 147 return 1; 148 if (!verify_userUnixName(userShortName)) 149 return 1; 150 if (!checkHomedirExistence()) 151 return 1; 152 153 NS_DURING 154 mNewUserPassword = [NSString stringWithUTF8String:kcpassword]; 155 NS_HANDLER 156 NSLog(@"failed to convert string"); 157 NS_ENDHANDLER 158 159 status = findEncryptionIdentities(&identityOrArray); 160 if (status)// || !identityArray || CFArrayGetCount(identityArray)==0) 161 { 162 sec_perror("Error when searching for encryption identities", status); 163 return status; 164 } 165 extractCertificatesFromIdentities(identityOrArray, &wrappingCertificates); 166 if (!wrappingCertificates || CFArrayGetCount(wrappingCertificates)==0) 167 { 168 sec_error("Error processing encryption identities"); 169 return status; 170 } 171 172 // add code here to append the cert from the master fv password keychain 173 174 sec_error("Creating user \"%s\" (%s)",userFullName,userShortName); 175 // what do we do now?? 176 _createUserAccount((NSArray *)wrappingCertificates); 177 178 return 0; 179} 180 181static BOOL authorize_me() 182{ 183 const char *kRightName = "system.preferences.accounts"; 184 AuthorizationFlags flags = kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed; // XXX remove kAuthorizationFlagInteractionAllowed 185 AuthorizationItem myAction = { kRightName, 0, 0, 0 }; 186 AuthorizationRights myRights = {1, &myAction}; 187// AuthorizationEnvironment myEnvironment = {0,}; 188 189 printf("Authorizing right %s\n", kRightName); 190 mAuthorization = [SFAuthorization authorizationWithFlags:flags 191 rights:&myRights environment:kAuthorizationEmptyEnvironment]; //&myEnvironment 192 193 if (!mAuthorization) 194 sec_error("Unable to obtain authorization for %s", kRightName); 195 196 return (mAuthorization!=0); 197// if (![myauth obtainWithRights:(const AuthorizationRights *)rights flags:(AuthorizationFlags)flags environment:(const AuthorizationEnvironment *)environment authorizedRights:(AuthorizationRights **)authorizedRights error:(NSError**)error; 198 199// [self setAuthenticator:[DSAuthenticator sharedDSAuthenticator]]; 200} 201 202static BOOL verify_userFullName(const char *userFullName) 203{ 204 // Verify user Full name 205 // Return true if OK to use 206 printf("Validating full name: %s\n", userFullName); 207 208 if ((userFullName == 0) || (strlen(userFullName) == 0)) 209 { 210 sec_error("User full name is required"); 211 return NO; 212 } 213 NS_DURING 214 mNewUserFullName = [NSString stringWithUTF8String:userFullName]; 215 NS_HANDLER 216 NSLog(@"failed to convert string"); 217 NS_ENDHANDLER 218 219 if(([mNewUserFullName caseInsensitiveCompare:@"admin"] != NSOrderedSame) && 220 ([ADMGroup findGroupByName:mNewUserFullName] != NULL)) 221 { 222 sec_error("User full name is not available (a group by that name exists)"); //USERNAME_IS_NOT_UNIQUE_SHORT 223 return NO; 224 } 225 226 if(![ADMUser isUserNameUnique:mNewUserFullName searchParent:NO]) 227 { 228 sec_error("User full name is not unique"); //USERNAME_IS_NOT_UNIQUE_SHORT 229 return NO; 230 } 231 return YES; 232} 233 234static BOOL verify_userUnixName(const char *userShortName) 235{ 236 // Verify unix-user name 237 // Return true if OK to use 238 239 if ((userShortName == 0) || (strlen(userShortName) == 0)) 240 { 241 sec_error("User short name is required"); 242 return NO; 243 } 244 245 printf("Validating short name: %s\n", userShortName); 246 NS_DURING 247 mNewUserName = [NSString stringWithUTF8String:userShortName]; 248 NS_HANDLER 249 NSLog(@"failed to convert string"); 250 NS_ENDHANDLER 251 252 if([mNewUserName isEqualToString:@"ftp"]) 253 return NO; 254 255 if([mNewUserName isEqualToString:@"public"]) 256 return NO; 257 258 if([mNewUserName length] == 0) 259 return NO; 260 261 if(![ADMUser isUserNameUnique:mNewUserName searchParent:NO]) 262 { 263 sec_error("User short name is not unique"); //USERNAME_IS_NOT_UNIQUE_SHORT 264 return NO; 265 } 266 267 if(![ADMUser isUnixNameValid:mNewUserName]) 268 { 269 sec_error("User short name is not a valid unix name"); //UNIXNAME_IS_NOT_VALID 270 return NO; 271 } 272 273 if(([mNewUserName caseInsensitiveCompare:@"admin"] != NSOrderedSame) && 274 ([ADMGroup findGroupByName:mNewUserName] != NULL)) 275 { 276 sec_error("User short name is not available (a group by that name exists)"); //USERNAME_IS_NOT_UNIQUE_SHORT 277 return NO; 278 } 279 280 // Orig: Fix for 3707901; Warn user if user's short name is admin 281 // We do not permit user's short name to be "admin" 282 if([mNewUserName caseInsensitiveCompare:@"admin"] == NSOrderedSame) 283 { 284 sec_error("User short name may not be \"admin\""); 285 return NO; 286 } 287 288 return YES; 289} 290 291static BOOL checkHomedirExistence() 292{ 293 // Check if home already exists - we disallow 294 NSFileManager * fm = [NSFileManager defaultManager]; 295 BOOL directory; 296 297 if([fm fileExistsAtPath:[@"/Users/" stringByAppendingPathComponent:mNewUserName] isDirectory:&directory]) 298 { 299 sec_error("Home directory already exists"); 300 return NO; 301 } 302 303 return YES; 304} 305 306static void _createUserAccount(NSArray *inCertificates) 307{ 308 // local version of [AddRecordController _createUserAccount:] 309 310 printf("Creating new user account: %s\n", [mNewUserName UTF8String]); 311 ADMUser * newUser = [ADMUser newUser]; 312 NSDictionary *inParameters =[NSDictionary dictionaryWithObject:inCertificates 313 forKey:kHomeDirectoryCertificates]; 314 315 [newUser setName:mNewUserName]; 316 [newUser setHomeDirectory:[newUser defaultHomeDirectory]]; 317 318 [newUser setUserCanChangePassword:YES]; 319 [newUser setUserCanChangeHint:YES]; 320 [newUser setUserCanChangePicture:YES]; 321 [newUser setUserCanChangeFullName:YES]; 322 [newUser setFullName:mNewUserFullName]; 323 324 [newUser setHint:@""]; 325 [newUser setPassword:mNewUserPassword]; 326 327 [newUser setHomeDirEncrypted:YES]; 328 [newUser commitChanges]; 329// [newUser createHomeDirectory]; 330 printf("Creating home directory...\n"); 331 if (![newUser createHomeDirectoryWithParameters:inParameters]) 332 sec_error("Failed to create home directory"); 333 334 [newUser setAdministrator:NO]; 335 336 [newUser createHTTPConfig]; 337 printf("New user account created and configured\n"); 338// [Utilities syncAFPIfNeeded]; 339} 340//>>>>>>>>>>>> don't forget to add the hash to "dsAttrTypeStandard:AuthenticationAuthority" 341/* 342 NSArray *forbiddenUserNames = [NSArray arrayWithObjects: 343 @"admin", @"ftp", @"public", 344 nil]; 345tolower 346- (NSUInteger)[forbiddenUserNames indexOfObject:(id)anObject; 347NSString 348*/ 349