1*af101e7fSchristos /*
2*af101e7fSchristos * The Initial Developer of the Original Code is International
3*af101e7fSchristos * Business Machines Corporation. Portions created by IBM
4*af101e7fSchristos * Corporation are Copyright (C) 2005 International Business
5*af101e7fSchristos * Machines Corporation. All Rights Reserved.
6*af101e7fSchristos *
7*af101e7fSchristos * This program is free software; you can redistribute it and/or modify
8*af101e7fSchristos * it under the terms of the Common Public License as published by
9*af101e7fSchristos * IBM Corporation; either version 1 of the License, or (at your option)
10*af101e7fSchristos * any later version.
11*af101e7fSchristos *
12*af101e7fSchristos * This program is distributed in the hope that it will be useful,
13*af101e7fSchristos * but WITHOUT ANY WARRANTY; without even the implied warranty of
14*af101e7fSchristos * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*af101e7fSchristos * Common Public License for more details.
16*af101e7fSchristos *
17*af101e7fSchristos * You should have received a copy of the Common Public License
18*af101e7fSchristos * along with this program; if not, a copy can be viewed at
19*af101e7fSchristos * http://www.opensource.org/licenses/cpl1.0.php.
20*af101e7fSchristos */
21*af101e7fSchristos
22*af101e7fSchristos #include "data_passwd.h"
23*af101e7fSchristos #include "data_common.h"
24*af101e7fSchristos
25*af101e7fSchristos #include <tpm_pkcs11.h>
26*af101e7fSchristos #include <tpm_utils.h>
27*af101e7fSchristos
28*af101e7fSchristos #include <stdlib.h>
29*af101e7fSchristos #include <unistd.h>
30*af101e7fSchristos #define _GNU_SOURCE
31*af101e7fSchristos #include <getopt.h>
32*af101e7fSchristos #include <errno.h>
33*af101e7fSchristos #include <string.h>
34*af101e7fSchristos #include <pwd.h>
35*af101e7fSchristos
36*af101e7fSchristos
37*af101e7fSchristos /*
38*af101e7fSchristos * Global variables
39*af101e7fSchristos */
40*af101e7fSchristos BOOL g_bSystem = FALSE; // Set SO pin specifier
41*af101e7fSchristos char *g_pszToken = NULL; // Token label to be used
42*af101e7fSchristos
43*af101e7fSchristos /*
44*af101e7fSchristos * parseCallback
45*af101e7fSchristos * Process the command specific options.
46*af101e7fSchristos */
47*af101e7fSchristos int
parseCallback(int a_iOpt,const char * a_pszOptArg)48*af101e7fSchristos parseCallback( int a_iOpt,
49*af101e7fSchristos const char *a_pszOptArg ) {
50*af101e7fSchristos
51*af101e7fSchristos switch ( a_iOpt ) {
52*af101e7fSchristos // Use the specified token label when finding the token
53*af101e7fSchristos case 'k':
54*af101e7fSchristos if ( !a_pszOptArg )
55*af101e7fSchristos return -1;
56*af101e7fSchristos
57*af101e7fSchristos g_pszToken = strdup( a_pszOptArg );
58*af101e7fSchristos break;
59*af101e7fSchristos
60*af101e7fSchristos case 's':
61*af101e7fSchristos g_bSystem = TRUE;
62*af101e7fSchristos break;
63*af101e7fSchristos }
64*af101e7fSchristos
65*af101e7fSchristos return 0;
66*af101e7fSchristos }
67*af101e7fSchristos
68*af101e7fSchristos /*
69*af101e7fSchristos * usageCallback
70*af101e7fSchristos * Display command usage information.
71*af101e7fSchristos */
72*af101e7fSchristos void
usageCallback(const char * a_pszCmd)73*af101e7fSchristos usageCallback( const char *a_pszCmd ) {
74*af101e7fSchristos
75*af101e7fSchristos logCmdHelp( a_pszCmd );
76*af101e7fSchristos logCmdOption( "-k, --token STRING",
77*af101e7fSchristos _("Use STRING to identify the label of the PKCS#11 token to be used") );
78*af101e7fSchristos logCmdOption( "-s, --security-officer",
79*af101e7fSchristos _("Change the security officer password") );
80*af101e7fSchristos }
81*af101e7fSchristos
82*af101e7fSchristos /*
83*af101e7fSchristos * parseCmd
84*af101e7fSchristos * Parse the command line options.
85*af101e7fSchristos */
86*af101e7fSchristos int
parseCmd(int a_iArgc,char ** a_pszArgv)87*af101e7fSchristos parseCmd( int a_iArgc,
88*af101e7fSchristos char **a_pszArgv ) {
89*af101e7fSchristos
90*af101e7fSchristos char *pszShortOpts = "k:s";
91*af101e7fSchristos struct option stLongOpts[] = {
92*af101e7fSchristos { "token", required_argument, NULL, 'k' },
93*af101e7fSchristos { "security-officer", no_argument, NULL, 's' },
94*af101e7fSchristos };
95*af101e7fSchristos int iNumLongOpts = sizeof( stLongOpts ) / sizeof( struct option );
96*af101e7fSchristos
97*af101e7fSchristos return genericOptHandler( a_iArgc, a_pszArgv,
98*af101e7fSchristos pszShortOpts, stLongOpts, iNumLongOpts,
99*af101e7fSchristos parseCallback, usageCallback );
100*af101e7fSchristos }
101*af101e7fSchristos
102*af101e7fSchristos int
main(int a_iArgc,char ** a_pszArgv)103*af101e7fSchristos main( int a_iArgc,
104*af101e7fSchristos char **a_pszArgv ) {
105*af101e7fSchristos
106*af101e7fSchristos int rc = 1;
107*af101e7fSchristos
108*af101e7fSchristos // Create buffers for PIN prompts for formatting using sprintf
109*af101e7fSchristos char szSoNewPinPrompt[ strlen( TOKEN_SO_NEW_PIN_PROMPT ) + 16 ];
110*af101e7fSchristos char szUserNewPinPrompt[ strlen( TOKEN_USER_NEW_PIN_PROMPT ) + 16 ];
111*af101e7fSchristos
112*af101e7fSchristos char *pszPrompt = NULL;
113*af101e7fSchristos char *pszPin = NULL;
114*af101e7fSchristos char *pszNewPin = NULL;
115*af101e7fSchristos
116*af101e7fSchristos CK_RV rv = CKR_OK;
117*af101e7fSchristos CK_USER_TYPE tUser = CKU_USER;
118*af101e7fSchristos CK_SESSION_HANDLE hSession = 0;
119*af101e7fSchristos
120*af101e7fSchristos // Set up i18n
121*af101e7fSchristos initIntlSys( );
122*af101e7fSchristos
123*af101e7fSchristos // Parse the command
124*af101e7fSchristos if ( parseCmd( a_iArgc, a_pszArgv ) == -1 )
125*af101e7fSchristos goto out;
126*af101e7fSchristos
127*af101e7fSchristos // Open the PKCS#11 TPM Token
128*af101e7fSchristos rv = openToken( g_pszToken );
129*af101e7fSchristos if ( rv != CKR_OK )
130*af101e7fSchristos goto out;
131*af101e7fSchristos
132*af101e7fSchristos // Make sure the token is initialized
133*af101e7fSchristos if ( !isTokenInitialized( ) ) {
134*af101e7fSchristos logMsg( TOKEN_NOT_INIT_ERROR );
135*af101e7fSchristos goto out;
136*af101e7fSchristos }
137*af101e7fSchristos
138*af101e7fSchristos // Open a session
139*af101e7fSchristos rv = openTokenSession( CKF_RW_SESSION, &hSession );
140*af101e7fSchristos if ( rv != CKR_OK )
141*af101e7fSchristos goto out;
142*af101e7fSchristos
143*af101e7fSchristos // Get the current password
144*af101e7fSchristos if ( g_bSystem ) {
145*af101e7fSchristos pszPrompt = TOKEN_SO_PIN_PROMPT;
146*af101e7fSchristos tUser = CKU_SO;
147*af101e7fSchristos }
148*af101e7fSchristos else {
149*af101e7fSchristos pszPrompt = TOKEN_USER_PIN_PROMPT;
150*af101e7fSchristos tUser = CKU_USER;
151*af101e7fSchristos }
152*af101e7fSchristos pszPin = getPlainPasswd( pszPrompt, FALSE );
153*af101e7fSchristos if ( !pszPin )
154*af101e7fSchristos goto out;
155*af101e7fSchristos
156*af101e7fSchristos // Login to the token
157*af101e7fSchristos rv = loginToken( hSession, tUser, pszPin );
158*af101e7fSchristos if ( rv != CKR_OK )
159*af101e7fSchristos goto out;
160*af101e7fSchristos
161*af101e7fSchristos // Get the new password
162*af101e7fSchristos if ( g_bSystem ) {
163*af101e7fSchristos sprintf( szSoNewPinPrompt, TOKEN_SO_NEW_PIN_PROMPT, getMinPinLen( ), getMaxPinLen( ) );
164*af101e7fSchristos pszPrompt = szSoNewPinPrompt;
165*af101e7fSchristos }
166*af101e7fSchristos else {
167*af101e7fSchristos sprintf( szUserNewPinPrompt, TOKEN_USER_NEW_PIN_PROMPT, getMinPinLen( ), getMaxPinLen( ) );
168*af101e7fSchristos pszPrompt = szUserNewPinPrompt;
169*af101e7fSchristos }
170*af101e7fSchristos
171*af101e7fSchristos while ( TRUE ) {
172*af101e7fSchristos // Prompt for a new SO password
173*af101e7fSchristos pszNewPin = getPlainPasswd( pszPrompt, TRUE );
174*af101e7fSchristos if ( !pszNewPin )
175*af101e7fSchristos goto out;
176*af101e7fSchristos
177*af101e7fSchristos // Set the new password
178*af101e7fSchristos rv = setPin( hSession, pszPin, pszNewPin );
179*af101e7fSchristos if ( rv == CKR_OK )
180*af101e7fSchristos break;
181*af101e7fSchristos
182*af101e7fSchristos if ( ( rv == CKR_PIN_INVALID ) || ( rv == CKR_PIN_LEN_RANGE ) )
183*af101e7fSchristos logError( TOKEN_INVALID_PIN );
184*af101e7fSchristos else
185*af101e7fSchristos goto out;
186*af101e7fSchristos
187*af101e7fSchristos shredPasswd( pszNewPin );
188*af101e7fSchristos }
189*af101e7fSchristos
190*af101e7fSchristos rc = 0;
191*af101e7fSchristos
192*af101e7fSchristos out:
193*af101e7fSchristos shredPasswd( pszPin );
194*af101e7fSchristos shredPasswd( pszNewPin );
195*af101e7fSchristos
196*af101e7fSchristos if ( hSession )
197*af101e7fSchristos closeTokenSession( hSession );
198*af101e7fSchristos
199*af101e7fSchristos closeToken( );
200*af101e7fSchristos
201*af101e7fSchristos if ( rc == 0 )
202*af101e7fSchristos logInfo( TOKEN_CMD_SUCCESS, a_pszArgv[ 0 ] );
203*af101e7fSchristos else
204*af101e7fSchristos logInfo( TOKEN_CMD_FAILED, a_pszArgv[ 0 ] );
205*af101e7fSchristos
206*af101e7fSchristos return rc;
207*af101e7fSchristos }
208