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 31BOOL useUnicode = FALSE; 32 33static 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 40static const char *pszGenShortOpts = "hvl:u"; 41 42void initIntlSys( ) { 43 44 setlocale( LC_ALL, "" ); 45 bindtextdomain( PACKAGE, LOCALEDIR ); 46 textdomain( PACKAGE ); 47} 48 49int 50genericOptHandler( 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 137void * __no_optimize 138__memset(void *s, int c, size_t n) 139{ 140 return memset(s, c, n); 141} 142 143/* 144 * This function should be called when you are done with a password 145 * the above getPasswd function to properly clean up. 146 */ 147void shredPasswd( char *a_pszPasswd ) { 148 149 if ( a_pszPasswd ) { 150 __memset( a_pszPasswd, 0, strlen( a_pszPasswd ) ); 151 free( a_pszPasswd ); 152 } 153} 154 155/* 156 * You must free the memory passed back to you when you are finished. 157 * Loop will always terminate by the second pass. 158 * Safest use of getpass is to zero the memory as soon as possible. 159 */ 160char *getPlainPasswd(const char *a_pszPrompt, BOOL a_bConfirm) { 161 int len; 162 return _getPasswd(a_pszPrompt, &len, a_bConfirm, FALSE); 163} 164 165#ifndef TSS_LIB_IS_12 166char *getPasswd(const char *a_pszPrompt, int* a_iLen, 167 BOOL a_bConfirm) { 168 return _getPasswd( a_pszPrompt, a_iLen, a_bConfirm, useUnicode); 169} 170#endif 171char *_getPasswd(const char *a_pszPrompt, int* a_iLen, 172 BOOL a_bConfirm, BOOL a_bUseUnicode) { 173 174 char *pszPrompt = (char *)a_pszPrompt; 175 char *pszPasswd = NULL; 176 char *pszRetPasswd = NULL; 177 178 do { 179 // Get password value from user - this is a static buffer 180 // and should never be freed 181 pszPasswd = getpass( pszPrompt ); 182 if (!pszPasswd && pszRetPasswd) { 183 shredPasswd( pszRetPasswd ); 184 return NULL; 185 } 186 187 // If this is confirmation pass check for match 188 if ( pszRetPasswd ) { 189 // Matched work complete 190 if ( strcmp( pszPasswd, pszRetPasswd ) == 0) 191 goto out; 192 193 // No match clean-up 194 logMsg( _("Passwords didn't match\n") ); 195 196 // pszPasswd will be cleaned up at out label 197 shredPasswd( pszRetPasswd ); 198 pszRetPasswd = NULL; 199 goto out; 200 } 201 202 // Save this passwd for next pass and/or return val 203 pszRetPasswd = strdup( pszPasswd ); 204 if ( !pszRetPasswd ) 205 goto out; 206 207 pszPrompt = _("Confirm password: "); 208 } while (a_bConfirm); 209 210out: 211 if (pszRetPasswd) { 212 *a_iLen = strlen(pszRetPasswd); 213 214 if (a_bUseUnicode) { 215 shredPasswd(pszRetPasswd); 216 pszRetPasswd = (char *)Trspi_Native_To_UNICODE((BYTE *)pszPasswd, (unsigned int *)a_iLen); 217 } 218 } 219 220 // pszPasswd is a static buffer, just clear it 221 if ( pszPasswd ) 222 __memset( pszPasswd, 0, strlen( pszPasswd ) ); 223 224 return pszRetPasswd; 225} 226 227/* 228 * You must free the memory passed back to you when you are finished. 229 */ 230char *getReply( const char *a_pszPrompt, int a_iMaxLen ) { 231 232 char *pszReply = NULL; 233 int iReplyLen = a_iMaxLen + 2; // Room for newline and trailing zero 234 235 if ( iReplyLen <= 0 ) 236 goto out; 237 238 pszReply = (char *)calloc( iReplyLen, 1 ); 239 if ( !pszReply ) 240 goto out; 241 242 logMsg( "%s", a_pszPrompt ); 243 pszReply = fgets( pszReply, iReplyLen, stdin ); 244 if ( !pszReply ) 245 goto out; 246 247 // Be certain that a complete line was read 248 if ( ( pszReply[ a_iMaxLen ] != '\n' ) && ( pszReply[ a_iMaxLen ] != '\0' ) ) { 249 free( pszReply ); 250 pszReply = NULL; 251 goto out; 252 } 253 254 for ( iReplyLen -= 1; iReplyLen >= 0; iReplyLen-- ) { 255 if ( pszReply[ iReplyLen ] == '\0' ) 256 continue; 257 258 if ( pszReply[ iReplyLen ] == '\n' ) 259 pszReply[ iReplyLen ] = '\0'; 260 break; 261 } 262 263out: 264 return pszReply; 265} 266