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 "keychain_utilities.h" 29#include "readline.h" 30#include "security.h" 31 32#include <stdio.h> 33#include <stdlib.h> 34#include <string.h> 35#include <unistd.h> 36#include <Security/SecKeychain.h> 37 38#include <Admin/LoginPrefs.h> 39 40static int 41do_lock_all(void) 42{ 43 OSStatus result = SecKeychainLockAll(); 44 if (result) 45 sec_perror("SecKeychainLockAll", result); 46 47 return result; 48} 49 50static int 51do_lock(const char *keychainName) 52{ 53 SecKeychainRef keychain = NULL; 54 OSStatus result; 55 56 if (keychainName) 57 { 58 keychain = keychain_open(keychainName); 59 if (!keychain) 60 { 61 result = 1; 62 goto loser; 63 } 64 } 65 66 result = SecKeychainLock(keychain); 67 if (result) 68 { 69 sec_error("SecKeychainLock %s: %s", keychainName ? keychainName : "<NULL>", sec_errstr(result)); 70 } 71 72loser: 73 if (keychain) 74 CFRelease(keychain); 75 76 return result; 77} 78 79int 80create_fv_user(int argc, char * const *argv) 81{ 82 char *keychainName = NULL; 83 int ch, result = 0; 84 Boolean lockAll = FALSE; 85 while ((ch = getopt(argc, argv, "ah")) != -1) 86 { 87 switch (ch) 88 { 89 case 'a': 90 lockAll = TRUE; 91 break; 92 case '?': 93 default: 94 return 2; /* @@@ Return 2 triggers usage message. */ 95 } 96 } 97 argc -= optind; 98 argv += optind; 99 100 if (argc == 1 && !lockAll) 101 { 102 keychainName = argv[0]; 103 if (*keychainName == '\0') 104 { 105 result = 2; 106 goto loser; 107 } 108 } 109 else if (argc != 0) 110 return 2; 111 112 if (lockAll) 113 result = do_lock_all(); 114 else 115 result = do_lock(keychainName); 116 117loser: 118 119 return result; 120} 121 122 123 // 124 // Verify user Full name 125 // 126 if([[mNewUserFullName stringValue] length] == 0) 127 { 128 // NSRunAlertPanel(LOCSTRING(@"USERNAME_IS_EMPTY"), LOCSTRING(@"USERNAME_IS_EMPTY_DESC"), LOCSTRING(@"OK"), NULL, NULL); 129 [mNewUserFullNameWarn setStringValue:LOCSTRING(@"USERNAME_IS_EMPTY_SHORT")]; 130 [self _showWarningForField:mNewUserFullName]; 131 return; 132 } 133 134 { 135 if(([[mNewUserFullName stringValue] caseInsensitiveCompare:@"admin"] != NSOrderedSame) && ([Group findGroupByName:[mNewUserFullName stringValue]] != NULL)) 136 { 137 // NSRunAlertPanel([NSString stringWithFormat:LOCSTRING(@"USERNAME_IS_NOT_AVAILABLE"), [mNewUserFullName stringValue]], LOCSTRING(@"USERNAME_IS_NOT_AVAILABLE_DESC"), LOCSTRING(@"OK"), NULL, NULL); 138 [mNewUserFullNameWarn setStringValue:LOCSTRING(@"USERNAME_IS_NOT_AVAILABLE_SHORT")]; 139 [self _showWarningForField:mNewUserFullName]; 140 return; 141 } 142 143 if(![User isUserNameUnique:[mNewUserFullName stringValue] searchParent:NO]) 144 { 145 // NSRunAlertPanel([NSString stringWithFormat:LOCSTRING(@"USERNAME_IS_NOT_UNIQUE"), [mNewUserFullName stringValue]], LOCSTRING(@"USERNAME_IS_NOT_UNIQUE_DESC"), LOCSTRING(@"OK"), NULL, NULL); 146 [mNewUserFullNameWarn setStringValue:LOCSTRING(@"USERNAME_IS_NOT_UNIQUE_SHORT")]; 147 [self _showWarningForField:mNewUserFullName]; 148 return; 149 } 150 } 151 152 153 // 154 // Verify unix-user name 155 // 156 if([[mNewUserName stringValue] length] == 0)) 157 { 158 // HACK to have the same behavior when user presses "Enter" and clicked "Save" 159 // right after entering full name (without even leaving the field) 160 [mNewUserName setStringValue:[User generateUnixNameUsingString:[mNewUserFullName stringValue]]]; 161 [[mNewUserName window] display]; 162 } 163 164 if([[mNewUserName stringValue] isEqualToString:@"ftp"]) 165 { 166 // NSRunAlertPanel(LOCSTRING(@"UNIXNAME_IS_PUBLIC"), LOCSTRING(@"UNIXNAME_IS_PUBLIC_DESC"), LOCSTRING(@"OK"), NULL, NULL); 167 [mNewUserNameWarn setStringValue:LOCSTRING(@"UNIXNAME_IS_FTP_SHORT")]; 168 [self _showWarningForField:mNewUserName]; 169 return; 170 } 171 172 if([[mNewUserName stringValue] isEqualToString:@"public"]) 173 { 174 // NSRunAlertPanel(LOCSTRING(@"UNIXNAME_IS_PUBLIC"), LOCSTRING(@"UNIXNAME_IS_PUBLIC_DESC"), LOCSTRING(@"OK"), NULL, NULL); 175 [mNewUserNameWarn setStringValue:LOCSTRING(@"UNIXNAME_IS_PUBLIC_SHORT")]; 176 [self _showWarningForField:mNewUserName]; 177 return; 178 } 179 180 if([[mNewUserName stringValue] length] == 0) 181 { 182 // NSRunAlertPanel(LOCSTRING(@"UNIXNAME_IS_EMPTY"), LOCSTRING(@"UNIXNAME_IS_EMPTY_DESC"), LOCSTRING(@"OK"), NULL, NULL); 183 [mNewUserNameWarn setStringValue:LOCSTRING(@"UNIXNAME_IS_EMPTY_SHORT")]; 184 [self _showWarningForField:mNewUserName]; 185 return; 186 } 187 188 if(![User isUserNameUnique:[mNewUserName stringValue] searchParent:NO]) 189 { 190 // NSRunAlertPanel([NSString stringWithFormat:LOCSTRING(@"UNIXNAME_IS_NOT_UNIQUE"), [mNewUserName stringValue]], LOCSTRING(@"UNIXNAME_IS_NOT_UNIQUE_DESC"), LOCSTRING(@"OK"), NULL, NULL); 191 [mNewUserNameWarn setStringValue:LOCSTRING(@"UNIXNAME_IS_NOT_UNIQUE_SHORT")]; 192 [self _showWarningForField:mNewUserName]; 193 return; 194 } 195 196 if(![User isUnixNameValid:[mNewUserName stringValue]]) 197 { 198 // NSRunAlertPanel([NSString stringWithFormat:LOCSTRING(@"UNIXNAME_IS_NOT_VALID"), [mNewUserName stringValue]], LOCSTRING(@"UNIXNAME_IS_NOT_VALID_DESC"), LOCSTRING(@"OK"), NULL, NULL); 199 [mNewUserNameWarn setStringValue:LOCSTRING(@"UNIXNAME_IS_NOT_VALID_SHORT")]; 200 [self _showWarningForField:mNewUserName]; 201 return; 202 } 203 204 if(([[mNewUserName stringValue] caseInsensitiveCompare:@"admin"] != NSOrderedSame) && ([Group findGroupByName:[mNewUserName stringValue]] != NULL)) 205 { 206 // NSRunAlertPanel([NSString stringWithFormat:LOCSTRING(@"USERNAME_IS_NOT_AVAILABLE"), [mNewUserName stringValue]], LOCSTRING(@"USERNAME_IS_NOT_AVAILABLE_DESC"), LOCSTRING(@"OK"), NULL, NULL); 207 [mNewUserNameWarn setStringValue:LOCSTRING(@"USERNAME_IS_NOT_AVAILABLE_SHORT")]; 208 [self _showWarningForField:mNewUserName]; 209 return; 210 } 211 212 // 213 // Verify Password 214 // 215 if(![[mNewUserPassword stringValue] isEqualToString:[mNewUserPasswordVerify stringValue]]) 216 { 217 // NSRunAlertPanel(LOCSTRING(@"PASS_VERIFY_ERR"), LOCSTRING(@"PASS_VERIFY_ERR_DESC"), LOCSTRING(@"OK"), NULL, NULL); 218 [mNewUserPassword setStringValue:@""]; 219 [mNewUserPasswordVerify setStringValue:@""]; 220 [mNewUserPasswordWarn setStringValue:LOCSTRING(@"PASS_VERIFY_ERR_SHORT")]; 221 [self _showWarningForField:mNewUserPassword]; 222 return; 223 } 224 225 // Warn about empty passowrd 226 if(![[mNewUserPassword stringValue] length]) 227 { 228 if(NSRunAlertPanel(LOCSTRING(@"PASS_IS_EMPTY_WARN"), LOCSTRING(@"PASS_IS_EMPTY_WARN_DESC"), LOCSTRING(@"CANCEL"), LOCSTRING(@"OK"), NULL) == NSOKButton) 229 { 230 [[mNewUserPassword window] makeFirstResponder:mNewUserPassword]; 231 return; 232 } 233 } 234 235 // Fix for 3707901 236 // Warn user if user's short name is admin 237 if([[mNewUserName stringValue] caseInsensitiveCompare:@"admin"] == NSOrderedSame) 238 { 239 if(NSRunAlertPanel(LOCSTRING(@"USERNAME_IS_ADMIN"), LOCSTRING(@"USERNAME_IS_ADMIN_DESCR"), LOCSTRING(@"OK"), LOCSTRING(@"CANCEL"), NULL) != NSOKButton) 240 { 241 [[mNewUserName window] makeFirstResponder:mNewUserName]; 242 return; 243 } 244 245 [mNewUserAdmin setState:NSOnState]; 246 } 247 248 // Check if home already exists 249 { 250 NSFileManager * fm = [NSFileManager defaultManager]; 251 BOOL directory; 252 NSString * username = [mNewUserName stringValue]; 253 254 if([fm fileExistsAtPath:[@"/Users/" stringByAppendingPathComponent:username] isDirectory:&directory]) 255 { 256 if(directory) 257 { 258 if(NSRunAlertPanel([NSString stringWithFormat:LOCSTRING(@"HOME_EXISTS_WARN"), username], LOCSTRING(@"HOME_EXISTS_WARN_DESCR"), LOCSTRING(@"CANCEL"), LOCSTRING(@"OK"), NULL) != NSCancelButton) return; 259 } 260 else 261 { 262 NSRunAlertPanel([NSString stringWithFormat:LOCSTRING(@"HOME_EXISTS_ERR"), username], LOCSTRING(@"HOME_EXISTS_ERR_DESCR"), LOCSTRING(@"OK"), NULL, NULL); 263 return; 264 } 265 } 266 } 267 268 if([mNewUserIsFV state] == NSOnState && (!SecFileVaultMasterPasswordEnabled(NULL))) 269 { 270 [mMasterPassword setStringValue:@""]; 271 [mMasterPasswordVerify setStringValue:@""]; 272 [mMasterPasswordHint setStringValue:@""]; 273 [mMasterPasswordWarn setStringValue:@""]; 274 [mNewUserWarningSign setHidden:YES]; 275 276 [self _setContentView:mMasterPasswordView displayAndAnimate:YES]; 277 [mNewUserSheet performSelector:@selector(makeFirstResponder:) withObject:mMasterPassword afterDelay:0.1]; 278 } 279 280 [[NSApplication sharedApplication] endSheet:[inSender window] returnCode:NSOKButton]; 281 [[inSender window] orderOut:[inSender window]]; 282