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 */
40 BOOL g_bSystem = FALSE; // Set SO pin specifier
41 char *g_pszToken = NULL; // Token label to be used
42
43 /*
44 * parseCallback
45 * Process the command specific options.
46 */
47 int
parseCallback(int a_iOpt,const char * a_pszOptArg)48 parseCallback( 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 */
72 void
usageCallback(const char * a_pszCmd)73 usageCallback( 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 */
86 int
parseCmd(int a_iArgc,char ** a_pszArgv)87 parseCmd( 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
102 int
main(int a_iArgc,char ** a_pszArgv)103 main( 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
192 out:
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