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 "data_passwd.h" 23#include "data_common.h" 24 25#include <tpm_pkcs11.h> 26#include <tpm_utils.h> 27 28#include <stdlib.h> 29#include <unistd.h> 30#define _GNU_SOURCE 31#include <getopt.h> 32#include <errno.h> 33#include <string.h> 34#include <pwd.h> 35 36 37/* 38 * Global variables 39 */ 40BOOL g_bSystem = FALSE; // Set SO pin specifier 41char *g_pszToken = NULL; // Token label to be used 42 43/* 44 * parseCallback 45 * Process the command specific options. 46 */ 47int 48parseCallback( int a_iOpt, 49 const char *a_pszOptArg ) { 50 51 switch ( a_iOpt ) { 52 // Use the specified token label when finding the token 53 case 'k': 54 if ( !a_pszOptArg ) 55 return -1; 56 57 g_pszToken = strdup( a_pszOptArg ); 58 break; 59 60 case 's': 61 g_bSystem = TRUE; 62 break; 63 } 64 65 return 0; 66} 67 68/* 69 * usageCallback 70 * Display command usage information. 71 */ 72void 73usageCallback( const char *a_pszCmd ) { 74 75 logCmdHelp( a_pszCmd ); 76 logCmdOption( "-k, --token STRING", 77 _("Use STRING to identify the label of the PKCS#11 token to be used") ); 78 logCmdOption( "-s, --security-officer", 79 _("Change the security officer password") ); 80} 81 82/* 83 * parseCmd 84 * Parse the command line options. 85 */ 86int 87parseCmd( int a_iArgc, 88 char **a_pszArgv ) { 89 90 char *pszShortOpts = "k:s"; 91 struct option stLongOpts[] = { 92 { "token", required_argument, NULL, 'k' }, 93 { "security-officer", no_argument, NULL, 's' }, 94 }; 95 int iNumLongOpts = sizeof( stLongOpts ) / sizeof( struct option ); 96 97 return genericOptHandler( a_iArgc, a_pszArgv, 98 pszShortOpts, stLongOpts, iNumLongOpts, 99 parseCallback, usageCallback ); 100} 101 102int 103main( int a_iArgc, 104 char **a_pszArgv ) { 105 106 int rc = 1; 107 108 // Create buffers for PIN prompts for formatting using sprintf 109 char szSoNewPinPrompt[ strlen( TOKEN_SO_NEW_PIN_PROMPT ) + 16 ]; 110 char szUserNewPinPrompt[ strlen( TOKEN_USER_NEW_PIN_PROMPT ) + 16 ]; 111 112 char *pszPrompt = NULL; 113 char *pszPin = NULL; 114 char *pszNewPin = NULL; 115 116 CK_RV rv = CKR_OK; 117 CK_USER_TYPE tUser = CKU_USER; 118 CK_SESSION_HANDLE hSession = 0; 119 120 // Set up i18n 121 initIntlSys( ); 122 123 // Parse the command 124 if ( parseCmd( a_iArgc, a_pszArgv ) == -1 ) 125 goto out; 126 127 // Open the PKCS#11 TPM Token 128 rv = openToken( g_pszToken ); 129 if ( rv != CKR_OK ) 130 goto out; 131 132 // Make sure the token is initialized 133 if ( !isTokenInitialized( ) ) { 134 logMsg( TOKEN_NOT_INIT_ERROR ); 135 goto out; 136 } 137 138 // Open a session 139 rv = openTokenSession( CKF_RW_SESSION, &hSession ); 140 if ( rv != CKR_OK ) 141 goto out; 142 143 // Get the current password 144 if ( g_bSystem ) { 145 pszPrompt = TOKEN_SO_PIN_PROMPT; 146 tUser = CKU_SO; 147 } 148 else { 149 pszPrompt = TOKEN_USER_PIN_PROMPT; 150 tUser = CKU_USER; 151 } 152 pszPin = getPlainPasswd( pszPrompt, FALSE ); 153 if ( !pszPin ) 154 goto out; 155 156 // Login to the token 157 rv = loginToken( hSession, tUser, pszPin ); 158 if ( rv != CKR_OK ) 159 goto out; 160 161 // Get the new password 162 if ( g_bSystem ) { 163 sprintf( szSoNewPinPrompt, TOKEN_SO_NEW_PIN_PROMPT, getMinPinLen( ), getMaxPinLen( ) ); 164 pszPrompt = szSoNewPinPrompt; 165 } 166 else { 167 sprintf( szUserNewPinPrompt, TOKEN_USER_NEW_PIN_PROMPT, getMinPinLen( ), getMaxPinLen( ) ); 168 pszPrompt = szUserNewPinPrompt; 169 } 170 171 while ( TRUE ) { 172 // Prompt for a new SO password 173 pszNewPin = getPlainPasswd( pszPrompt, TRUE ); 174 if ( !pszNewPin ) 175 goto out; 176 177 // Set the new password 178 rv = setPin( hSession, pszPin, pszNewPin ); 179 if ( rv == CKR_OK ) 180 break; 181 182 if ( ( rv == CKR_PIN_INVALID ) || ( rv == CKR_PIN_LEN_RANGE ) ) 183 logError( TOKEN_INVALID_PIN ); 184 else 185 goto out; 186 187 shredPasswd( pszNewPin ); 188 } 189 190 rc = 0; 191 192out: 193 shredPasswd( pszPin ); 194 shredPasswd( pszNewPin ); 195 196 if ( hSession ) 197 closeTokenSession( hSession ); 198 199 closeToken( ); 200 201 if ( rc == 0 ) 202 logInfo( TOKEN_CMD_SUCCESS, a_pszArgv[ 0 ] ); 203 else 204 logInfo( TOKEN_CMD_FAILED, a_pszArgv[ 0 ] ); 205 206 return rc; 207} 208