1/* 2 * Copyright (c) 2003-2006 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 * tokenadmin.c 24 */ 25 26#include "tokenadmin.h" 27 28#include "readline.h" 29 30//#include "cmsutil.h" 31//#include "db_commands.h" 32#include "create_fv_user.h" 33//#include "authz.h" 34 35#include <ctype.h> 36#include <stdio.h> 37#include <stdlib.h> 38#include <string.h> 39#include <unistd.h> 40 41#import <Foundation/Foundation.h> 42 43#include <CoreFoundation/CFRunLoop.h> 44#include <Security/SecBasePriv.h> 45#include <security_asn1/secerr.h> 46 47/* Maximum length of an input line in interactive mode. */ 48#define MAX_LINE_LEN 4096 49/* Maximum number of arguments on an input line in interactive mode. */ 50#define MAX_ARGS 32 51 52/* Entry in commands array for a command. */ 53typedef struct command 54{ 55 const char *c_name; /* name of the command. */ 56 command_func c_func; /* function to execute the command. */ 57 const char *c_usage; /* usage sting for command. */ 58 const char *c_help; /* help string for (or description of) command. */ 59} command; 60 61/* The default prompt. */ 62const char *prompt_string = "tokenadmin> "; 63 64/* The name of this program. */ 65const char *prog_name; 66 67 68/* Forward declarations of static functions. */ 69static int help(int argc, char * const *argv); 70 71/* 72 * The command array itself. 73 * Add commands here at will. 74 * Matching is done on a prefix basis. The first command in the array 75 * gets matched first. 76 */ 77const command commands[] = 78{ 79 { "help", help, 80 "[command ...]", 81 "Show all commands or show usage for a command." }, 82 83 { "create-fv-user", create_fv_user, 84 "-u <short user Name> -l <long user Name> [-p password]\n" 85 " -u Use the argument as the short (i.e. unix) name for the new user.\n" 86 " -l Use the argument as the long name for the new user.\n" 87 " -p The option keychain password for the account.\n" 88 "With no parameters display usage.", 89 "Create a new FileVault user protected by a token." }, 90 91 {} 92}; 93 94/* Global variables. */ 95int do_quiet = 0; 96int do_verbose = 0; 97 98/* Return 1 if name matches command. */ 99static int 100match_command(const char *command, const char *name) 101{ 102 return !strncmp(command, name, strlen(name)); 103} 104 105/* The help command. */ 106static int 107help(int argc, char * const *argv) 108{ 109 const command *c; 110 111 if (argc > 1) 112 { 113 char * const *arg; 114 for (arg = argv + 1; *arg; ++arg) 115 { 116 int found = 0; 117 118 for (c = commands; c->c_name; ++c) 119 { 120 if (match_command(c->c_name, *arg)) 121 { 122 found = 1; 123 break; 124 } 125 } 126 127 if (found) 128 printf("Usage: %s %s\n", c->c_name, c->c_usage); 129 else 130 { 131 sec_error("%s: no such command: %s", argv[0], *arg); 132 return 1; 133 } 134 } 135 } 136 else 137 { 138 for (c = commands; c->c_name; ++c) 139 printf(" %-17s %s\n", c->c_name, c->c_help); 140 } 141 142 return 0; 143} 144 145/* Print a (hopefully) useful usage message. */ 146static int 147usage(void) 148{ 149 printf( 150 "Usage: %s [-h] [-q] [-v] [command] [opt ...]\n" 151 " -q Be less verbose.\n" 152 " -v Be more verbose about what's going on.\n" 153 "%s commands are:\n", prog_name, prog_name); 154 help(0, NULL); 155 return 2; 156} 157 158/* Execute a single command. */ 159static int 160execute_command(int argc, char * const *argv) 161{ 162 const command *c; 163 int found = 0; 164 165 /* Nothing to do. */ 166 if (argc == 0) 167 return 0; 168 169 for (c = commands; c->c_name; ++c) 170 { 171 if (match_command(c->c_name, argv[0])) 172 { 173 found = 1; 174 break; 175 } 176 } 177 178 if (found) 179 { 180 int result; 181 182 /* Reset getopt for command proc. */ 183 optind = 1; 184 optreset = 1; 185 186 if (do_verbose) 187 { 188 int ix; 189 190 fprintf(stderr, "%s", c->c_name); 191 for (ix = 1; ix < argc; ++ix) 192 fprintf(stderr, " \"%s\"", argv[ix]); 193 fprintf(stderr, "\n"); 194 } 195 196 result = c->c_func(argc, argv); 197 if (result == 2) 198 fprintf(stderr, "Usage: %s %s\n %s\n", c->c_name, c->c_usage, c->c_help); 199 200 return result; 201 } 202 else 203 { 204 sec_error("unknown command \"%s\"", argv[0]); 205 return 1; 206 } 207} 208 209static void 210receive_notifications(void) 211{ 212 /* Run the CFRunloop to get any pending notifications. */ 213 while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, TRUE) == kCFRunLoopRunHandledSource); 214} 215 216 217const char * 218sec_errstr(int err) 219{ 220 const char *errString; 221// if (IS_SEC_ERROR(err)) 222 // errString = SECErrorString(err); 223 // else 224 errString = cssmErrorString(err); 225 return errString; 226} 227 228void 229sec_error(const char *msg, ...) 230{ 231 va_list args; 232 233 fprintf(stderr, "%s: ", prog_name); 234 235 va_start(args, msg); 236 vfprintf(stderr, msg, args); 237 va_end(args); 238 239 fprintf(stderr, "\n"); 240} 241 242void 243sec_perror(const char *msg, int err) 244{ 245 sec_error("%s: %s", msg, sec_errstr(err)); 246} 247 248int 249main(int argc, char * const *argv) 250{ 251 int result = 0; 252 int do_help = 0; 253 int ch; 254 const char *shortUserName = NULL; 255 const char *longUserName = NULL; 256 const char *password = NULL; 257 258 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 259 /* Remember my name. */ 260 prog_name = strrchr(argv[0], '/'); 261 prog_name = prog_name ? prog_name + 1 : argv[0]; 262 263 /* Do getopt stuff for global options. */ 264 optind = 1; 265 optreset = 1; 266 while ((ch = getopt(argc, argv, "hqv")) != -1) 267 { 268 switch (ch) 269 { 270 case 'h': 271 do_help = 1; 272 break; 273 case 'q': 274 do_quiet = 1; 275 break; 276 case 'v': 277 do_verbose = 1; 278 break; 279 case '?': 280 default: 281 return usage(); 282 } 283 } 284 285 argc -= optind; 286 argv += optind; 287 288 if (do_help) 289 { 290 /* Munge argc/argv so that argv[0] is something. */ 291 return help(argc + 1, argv - 1); 292 } 293 else if (argc > 0) 294 { 295 receive_notifications(); 296 result = execute_command(argc, argv); 297 if (result == 2) 298 usage(); 299 receive_notifications(); 300 } 301 else 302 result = usage(); 303 304 [pool release]; 305 return result; 306} 307