1 1.1 christos /* 2 1.1 christos * The Initial Developer of the Original Code is International 3 1.1 christos * Business Machines Corporation. Portions created by IBM 4 1.1 christos * Corporation are Copyright (C) 2005 International Business 5 1.1 christos * Machines Corporation. All Rights Reserved. 6 1.1 christos * 7 1.1 christos * This program is free software; you can redistribute it and/or modify 8 1.1 christos * it under the terms of the Common Public License as published by 9 1.1 christos * IBM Corporation; either version 1 of the License, or (at your option) 10 1.1 christos * any later version. 11 1.1 christos * 12 1.1 christos * This program is distributed in the hope that it will be useful, 13 1.1 christos * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1 christos * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 1.1 christos * Common Public License for more details. 16 1.1 christos * 17 1.1 christos * You should have received a copy of the Common Public License 18 1.1 christos * along with this program; if not, a copy can be viewed at 19 1.1 christos * http://www.opensource.org/licenses/cpl1.0.php. 20 1.1 christos */ 21 1.1 christos 22 1.1 christos #include "config.h" 23 1.1 christos #include <unistd.h> 24 1.1 christos #include <stdlib.h> 25 1.1 christos #include <trousers/tss.h> 26 1.1 christos #include <trousers/trousers.h> 27 1.1 christos 28 1.1 christos #include "tpm_tspi.h" 29 1.1 christos #include "tpm_utils.h" 30 1.1 christos 31 1.1 christos BOOL useUnicode = FALSE; 32 1.1 christos 33 1.1 christos static const struct option sGenLongOpts[] = { 34 1.1 christos { "help", no_argument, NULL, 'h' }, 35 1.1 christos { "version", no_argument, NULL, 'v' }, 36 1.1 christos { "log", required_argument, NULL, 'l' }, 37 1.1 christos { "unicode", no_argument, NULL, 'u' }, 38 1.1 christos }; 39 1.1 christos 40 1.1 christos static const char *pszGenShortOpts = "hvl:u"; 41 1.1 christos 42 1.1 christos void initIntlSys( ) { 43 1.1 christos 44 1.1 christos setlocale( LC_ALL, "" ); 45 1.1 christos bindtextdomain( PACKAGE, LOCALEDIR ); 46 1.1 christos textdomain( PACKAGE ); 47 1.1 christos } 48 1.1 christos 49 1.1 christos int 50 1.1 christos genericOptHandler( int a_iNumArgs, char **a_pszArgs, 51 1.1 christos const char *a_pszShortOpts, 52 1.1 christos struct option *a_sLongOpts, int a_iNumOpts, 53 1.1 christos CmdOptParser a_tCmdOptParser, CmdHelpFunction a_tCmdHelpFunction ) { 54 1.1 christos 55 1.1 christos CmdHelpFunction tCmdHelp = ( a_tCmdHelpFunction ) ? a_tCmdHelpFunction 56 1.1 christos : logCmdHelp; 57 1.1 christos 58 1.1 christos char szShortOpts[strlen( pszGenShortOpts ) 59 1.1 christos + ( ( a_pszShortOpts == NULL ) ? 0 : strlen( a_pszShortOpts ) ) 60 1.1 christos + 1]; 61 1.1 christos 62 1.1 christos int iNumGenLongOpts = sizeof( sGenLongOpts ) / sizeof( struct option ); 63 1.1 christos struct option sLongOpts[iNumGenLongOpts + a_iNumOpts + 1]; 64 1.1 christos 65 1.1 christos int iOpt; 66 1.1 christos int rc; 67 1.1 christos 68 1.1 christos strcpy( szShortOpts, pszGenShortOpts); 69 1.1 christos if ( a_pszShortOpts ) 70 1.1 christos strcat( szShortOpts, a_pszShortOpts ); 71 1.1 christos 72 1.1.1.2 christos __memset( sLongOpts, 0, sizeof( sLongOpts ) ); 73 1.1 christos memcpy( sLongOpts, sGenLongOpts, sizeof( sGenLongOpts ) ); 74 1.1 christos if ( a_sLongOpts ) { 75 1.1 christos memcpy( sLongOpts + iNumGenLongOpts, 76 1.1 christos a_sLongOpts, 77 1.1 christos a_iNumOpts * sizeof( struct option ) ); 78 1.1 christos } 79 1.1 christos 80 1.1 christos while ( ( iOpt = getopt_long( a_iNumArgs, a_pszArgs, 81 1.1 christos szShortOpts, sLongOpts, NULL ) ) != -1 ) { 82 1.1 christos 83 1.1 christos switch ( iOpt ) { 84 1.1 christos case 'h': 85 1.1 christos tCmdHelp( a_pszArgs[0] ); 86 1.1 christos return -1; 87 1.1 christos 88 1.1 christos case 'v': 89 1.1 christos logMsg( _("%s version: %s\n"), a_pszArgs[0], CMD_VERSION ); 90 1.1 christos return -1; 91 1.1 christos 92 1.1 christos case 'l': 93 1.1 christos if ( !optarg ) { 94 1.1 christos tCmdHelp( a_pszArgs[0] ); 95 1.1 christos return -1; 96 1.1 christos } 97 1.1 christos 98 1.1 christos if ( strcmp( optarg, LOG_NONE ) == 0 ) 99 1.1 christos iLogLevel = LOG_LEVEL_NONE; 100 1.1 christos else if ( strcmp( optarg, LOG_ERROR ) == 0 ) 101 1.1 christos iLogLevel = LOG_LEVEL_ERROR; 102 1.1 christos else if ( strcmp( optarg, LOG_INFO ) == 0 ) 103 1.1 christos iLogLevel = LOG_LEVEL_INFO; 104 1.1 christos else if ( strcmp( optarg, LOG_DEBUG ) == 0 ) 105 1.1 christos iLogLevel = LOG_LEVEL_DEBUG; 106 1.1 christos else { 107 1.1 christos logMsg( _("Valid log levels are: %s, %s, %s, %s\n"), 108 1.1 christos LOG_NONE, 109 1.1 christos LOG_ERROR, 110 1.1 christos LOG_INFO, 111 1.1 christos LOG_DEBUG ); 112 1.1 christos tCmdHelp( a_pszArgs[0] ); 113 1.1 christos return -1; 114 1.1 christos } 115 1.1 christos break; 116 1.1 christos case 'u': 117 1.1 christos useUnicode = TRUE; 118 1.1 christos break; 119 1.1 christos case '?': 120 1.1 christos tCmdHelp( a_pszArgs[0] ); 121 1.1 christos return -1; 122 1.1 christos 123 1.1 christos default: 124 1.1 christos if ( !a_tCmdOptParser ) 125 1.1 christos return -1; 126 1.1 christos 127 1.1 christos rc = a_tCmdOptParser( iOpt, optarg ); 128 1.1 christos if ( rc != 0 ) 129 1.1 christos return rc; 130 1.1 christos break; 131 1.1 christos } 132 1.1 christos } 133 1.1 christos 134 1.1 christos return 0; 135 1.1 christos } 136 1.1 christos 137 1.1.1.2 christos void * __no_optimize 138 1.1.1.2 christos __memset(void *s, int c, size_t n) 139 1.1.1.2 christos { 140 1.1.1.2 christos return memset(s, c, n); 141 1.1.1.2 christos } 142 1.1.1.2 christos 143 1.1 christos /* 144 1.1 christos * This function should be called when you are done with a password 145 1.1 christos * the above getPasswd function to properly clean up. 146 1.1 christos */ 147 1.1 christos void shredPasswd( char *a_pszPasswd ) { 148 1.1 christos 149 1.1 christos if ( a_pszPasswd ) { 150 1.1.1.2 christos __memset( a_pszPasswd, 0, strlen( a_pszPasswd ) ); 151 1.1 christos free( a_pszPasswd ); 152 1.1 christos } 153 1.1 christos } 154 1.1 christos 155 1.1 christos /* 156 1.1 christos * You must free the memory passed back to you when you are finished. 157 1.1 christos * Loop will always terminate by the second pass. 158 1.1 christos * Safest use of getpass is to zero the memory as soon as possible. 159 1.1 christos */ 160 1.1 christos char *getPlainPasswd(const char *a_pszPrompt, BOOL a_bConfirm) { 161 1.1 christos int len; 162 1.1 christos return _getPasswd(a_pszPrompt, &len, a_bConfirm, FALSE); 163 1.1 christos } 164 1.1 christos 165 1.1 christos #ifndef TSS_LIB_IS_12 166 1.1 christos char *getPasswd(const char *a_pszPrompt, int* a_iLen, 167 1.1 christos BOOL a_bConfirm) { 168 1.1 christos return _getPasswd( a_pszPrompt, a_iLen, a_bConfirm, useUnicode); 169 1.1 christos } 170 1.1 christos #endif 171 1.1 christos char *_getPasswd(const char *a_pszPrompt, int* a_iLen, 172 1.1 christos BOOL a_bConfirm, BOOL a_bUseUnicode) { 173 1.1 christos 174 1.1 christos char *pszPrompt = (char *)a_pszPrompt; 175 1.1 christos char *pszPasswd = NULL; 176 1.1 christos char *pszRetPasswd = NULL; 177 1.1 christos 178 1.1 christos do { 179 1.1 christos // Get password value from user - this is a static buffer 180 1.1 christos // and should never be freed 181 1.1 christos pszPasswd = getpass( pszPrompt ); 182 1.1 christos if (!pszPasswd && pszRetPasswd) { 183 1.1 christos shredPasswd( pszRetPasswd ); 184 1.1 christos return NULL; 185 1.1 christos } 186 1.1 christos 187 1.1 christos // If this is confirmation pass check for match 188 1.1 christos if ( pszRetPasswd ) { 189 1.1 christos // Matched work complete 190 1.1 christos if ( strcmp( pszPasswd, pszRetPasswd ) == 0) 191 1.1 christos goto out; 192 1.1 christos 193 1.1 christos // No match clean-up 194 1.1 christos logMsg( _("Passwords didn't match\n") ); 195 1.1 christos 196 1.1 christos // pszPasswd will be cleaned up at out label 197 1.1 christos shredPasswd( pszRetPasswd ); 198 1.1 christos pszRetPasswd = NULL; 199 1.1 christos goto out; 200 1.1 christos } 201 1.1 christos 202 1.1 christos // Save this passwd for next pass and/or return val 203 1.1 christos pszRetPasswd = strdup( pszPasswd ); 204 1.1 christos if ( !pszRetPasswd ) 205 1.1 christos goto out; 206 1.1 christos 207 1.1 christos pszPrompt = _("Confirm password: "); 208 1.1 christos } while (a_bConfirm); 209 1.1 christos 210 1.1 christos out: 211 1.1 christos if (pszRetPasswd) { 212 1.1 christos *a_iLen = strlen(pszRetPasswd); 213 1.1 christos 214 1.1 christos if (a_bUseUnicode) { 215 1.1 christos shredPasswd(pszRetPasswd); 216 1.1 christos pszRetPasswd = (char *)Trspi_Native_To_UNICODE((BYTE *)pszPasswd, (unsigned int *)a_iLen); 217 1.1 christos } 218 1.1 christos } 219 1.1 christos 220 1.1 christos // pszPasswd is a static buffer, just clear it 221 1.1 christos if ( pszPasswd ) 222 1.1.1.2 christos __memset( pszPasswd, 0, strlen( pszPasswd ) ); 223 1.1 christos 224 1.1 christos return pszRetPasswd; 225 1.1 christos } 226 1.1 christos 227 1.1 christos /* 228 1.1 christos * You must free the memory passed back to you when you are finished. 229 1.1 christos */ 230 1.1 christos char *getReply( const char *a_pszPrompt, int a_iMaxLen ) { 231 1.1 christos 232 1.1 christos char *pszReply = NULL; 233 1.1 christos int iReplyLen = a_iMaxLen + 2; // Room for newline and trailing zero 234 1.1 christos 235 1.1 christos if ( iReplyLen <= 0 ) 236 1.1 christos goto out; 237 1.1 christos 238 1.1 christos pszReply = (char *)calloc( iReplyLen, 1 ); 239 1.1 christos if ( !pszReply ) 240 1.1 christos goto out; 241 1.1 christos 242 1.1 christos logMsg( "%s", a_pszPrompt ); 243 1.1 christos pszReply = fgets( pszReply, iReplyLen, stdin ); 244 1.1 christos if ( !pszReply ) 245 1.1 christos goto out; 246 1.1 christos 247 1.1 christos // Be certain that a complete line was read 248 1.1 christos if ( ( pszReply[ a_iMaxLen ] != '\n' ) && ( pszReply[ a_iMaxLen ] != '\0' ) ) { 249 1.1 christos free( pszReply ); 250 1.1 christos pszReply = NULL; 251 1.1 christos goto out; 252 1.1 christos } 253 1.1 christos 254 1.1 christos for ( iReplyLen -= 1; iReplyLen >= 0; iReplyLen-- ) { 255 1.1 christos if ( pszReply[ iReplyLen ] == '\0' ) 256 1.1 christos continue; 257 1.1 christos 258 1.1 christos if ( pszReply[ iReplyLen ] == '\n' ) 259 1.1 christos pszReply[ iReplyLen ] = '\0'; 260 1.1 christos break; 261 1.1 christos } 262 1.1 christos 263 1.1 christos out: 264 1.1 christos return pszReply; 265 1.1 christos } 266