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