/* * The Initial Developer of the Original Code is International * Business Machines Corporation. Portions created by IBM * Corporation are Copyright (C) 2005 International Business * Machines Corporation. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Common Public License as published by * IBM Corporation; either version 1 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Common Public License for more details. * * You should have received a copy of the Common Public License * along with this program; if not, a copy can be viewed at * http://www.opensource.org/licenses/cpl1.0.php. */ #include "config.h" #include #include #include #include #include "tpm_tspi.h" #include "tpm_utils.h" BOOL useUnicode = FALSE; static const struct option sGenLongOpts[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "log", required_argument, NULL, 'l' }, { "unicode", no_argument, NULL, 'u' }, }; static const char *pszGenShortOpts = "hvl:u"; void initIntlSys( ) { setlocale( LC_ALL, "" ); bindtextdomain( PACKAGE, LOCALEDIR ); textdomain( PACKAGE ); } int genericOptHandler( int a_iNumArgs, char **a_pszArgs, const char *a_pszShortOpts, struct option *a_sLongOpts, int a_iNumOpts, CmdOptParser a_tCmdOptParser, CmdHelpFunction a_tCmdHelpFunction ) { CmdHelpFunction tCmdHelp = ( a_tCmdHelpFunction ) ? a_tCmdHelpFunction : logCmdHelp; char szShortOpts[strlen( pszGenShortOpts ) + ( ( a_pszShortOpts == NULL ) ? 0 : strlen( a_pszShortOpts ) ) + 1]; int iNumGenLongOpts = sizeof( sGenLongOpts ) / sizeof( struct option ); struct option sLongOpts[iNumGenLongOpts + a_iNumOpts + 1]; int iOpt; int rc; strcpy( szShortOpts, pszGenShortOpts); if ( a_pszShortOpts ) strcat( szShortOpts, a_pszShortOpts ); __memset( sLongOpts, 0, sizeof( sLongOpts ) ); memcpy( sLongOpts, sGenLongOpts, sizeof( sGenLongOpts ) ); if ( a_sLongOpts ) { memcpy( sLongOpts + iNumGenLongOpts, a_sLongOpts, a_iNumOpts * sizeof( struct option ) ); } while ( ( iOpt = getopt_long( a_iNumArgs, a_pszArgs, szShortOpts, sLongOpts, NULL ) ) != -1 ) { switch ( iOpt ) { case 'h': tCmdHelp( a_pszArgs[0] ); return -1; case 'v': logMsg( _("%s version: %s\n"), a_pszArgs[0], CMD_VERSION ); return -1; case 'l': if ( !optarg ) { tCmdHelp( a_pszArgs[0] ); return -1; } if ( strcmp( optarg, LOG_NONE ) == 0 ) iLogLevel = LOG_LEVEL_NONE; else if ( strcmp( optarg, LOG_ERROR ) == 0 ) iLogLevel = LOG_LEVEL_ERROR; else if ( strcmp( optarg, LOG_INFO ) == 0 ) iLogLevel = LOG_LEVEL_INFO; else if ( strcmp( optarg, LOG_DEBUG ) == 0 ) iLogLevel = LOG_LEVEL_DEBUG; else { logMsg( _("Valid log levels are: %s, %s, %s, %s\n"), LOG_NONE, LOG_ERROR, LOG_INFO, LOG_DEBUG ); tCmdHelp( a_pszArgs[0] ); return -1; } break; case 'u': useUnicode = TRUE; break; case '?': tCmdHelp( a_pszArgs[0] ); return -1; default: if ( !a_tCmdOptParser ) return -1; rc = a_tCmdOptParser( iOpt, optarg ); if ( rc != 0 ) return rc; break; } } return 0; } void * __no_optimize __memset(void *s, int c, size_t n) { return memset(s, c, n); } /* * This function should be called when you are done with a password * the above getPasswd function to properly clean up. */ void shredPasswd( char *a_pszPasswd ) { if ( a_pszPasswd ) { __memset( a_pszPasswd, 0, strlen( a_pszPasswd ) ); free( a_pszPasswd ); } } /* * You must free the memory passed back to you when you are finished. * Loop will always terminate by the second pass. * Safest use of getpass is to zero the memory as soon as possible. */ char *getPlainPasswd(const char *a_pszPrompt, BOOL a_bConfirm) { int len; return _getPasswd(a_pszPrompt, &len, a_bConfirm, FALSE); } #ifndef TSS_LIB_IS_12 char *getPasswd(const char *a_pszPrompt, int* a_iLen, BOOL a_bConfirm) { return _getPasswd( a_pszPrompt, a_iLen, a_bConfirm, useUnicode); } #endif char *_getPasswd(const char *a_pszPrompt, int* a_iLen, BOOL a_bConfirm, BOOL a_bUseUnicode) { char *pszPrompt = (char *)a_pszPrompt; char *pszPasswd = NULL; char *pszRetPasswd = NULL; do { // Get password value from user - this is a static buffer // and should never be freed pszPasswd = getpass( pszPrompt ); if (!pszPasswd && pszRetPasswd) { shredPasswd( pszRetPasswd ); return NULL; } // If this is confirmation pass check for match if ( pszRetPasswd ) { // Matched work complete if ( strcmp( pszPasswd, pszRetPasswd ) == 0) goto out; // No match clean-up logMsg( _("Passwords didn't match\n") ); // pszPasswd will be cleaned up at out label shredPasswd( pszRetPasswd ); pszRetPasswd = NULL; goto out; } // Save this passwd for next pass and/or return val pszRetPasswd = strdup( pszPasswd ); if ( !pszRetPasswd ) goto out; pszPrompt = _("Confirm password: "); } while (a_bConfirm); out: if (pszRetPasswd) { *a_iLen = strlen(pszRetPasswd); if (a_bUseUnicode) { shredPasswd(pszRetPasswd); pszRetPasswd = (char *)Trspi_Native_To_UNICODE((BYTE *)pszPasswd, (unsigned int *)a_iLen); } } // pszPasswd is a static buffer, just clear it if ( pszPasswd ) __memset( pszPasswd, 0, strlen( pszPasswd ) ); return pszRetPasswd; } /* * You must free the memory passed back to you when you are finished. */ char *getReply( const char *a_pszPrompt, int a_iMaxLen ) { char *pszReply = NULL; int iReplyLen = a_iMaxLen + 2; // Room for newline and trailing zero if ( iReplyLen <= 0 ) goto out; pszReply = (char *)calloc( iReplyLen, 1 ); if ( !pszReply ) goto out; logMsg( "%s", a_pszPrompt ); pszReply = fgets( pszReply, iReplyLen, stdin ); if ( !pszReply ) goto out; // Be certain that a complete line was read if ( ( pszReply[ a_iMaxLen ] != '\n' ) && ( pszReply[ a_iMaxLen ] != '\0' ) ) { free( pszReply ); pszReply = NULL; goto out; } for ( iReplyLen -= 1; iReplyLen >= 0; iReplyLen-- ) { if ( pszReply[ iReplyLen ] == '\0' ) continue; if ( pszReply[ iReplyLen ] == '\n' ) pszReply[ iReplyLen ] = '\0'; break; } out: return pszReply; }