VirtualBox

source: vbox/trunk/src/VBox/Runtime/tools/RTMkPasswd.cpp@ 103914

Last change on this file since 103914 was 102488, checked in by vboxsync, 12 months ago

IPRT,Main/Unattended: Added a simplified API for the SHAcrypt functionality (the two step approach isn't really something we'll be needing). Corrected documentation, added constant for max output size (RTSHA512_HASH_SIZE*4 isn't a good choice) and whatnot. Added missing round count range checks. Fixed rounding error in output string buffer requirements; actually replacing the whole stuff by just calculating the size upfront before formatting anything. bugref:10551

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.6 KB
Line 
1/* $Id: RTMkPasswd.cpp 102488 2023-12-05 23:53:09Z vboxsync $ */
2/** @file
3 * IPRT - Makes passwords.
4 */
5
6/*
7 * Copyright (C) 2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/buildconfig.h>
42#include <iprt/crypto/shacrypt.h>
43#include <iprt/err.h>
44#include <iprt/initterm.h>
45#include <iprt/getopt.h>
46#include <iprt/mem.h>
47#include <iprt/message.h>
48#include <iprt/rand.h>
49#include <iprt/sha.h>
50#include <iprt/stream.h>
51#include <iprt/string.h>
52
53
54/*********************************************************************************************************************************
55* Structures and Typedefs *
56*********************************************************************************************************************************/
57/** Method type. */
58typedef enum RTMKPASSWDMETHOD
59{
60 RTMKPASSWDMETHOD_SHA256,
61 RTMKPASSWDMETHOD_SHA512
62} RTMKPASSWDMETHOD;
63
64
65
66int main(int argc, char **argv)
67{
68 RTR3InitExe(argc, &argv, 0);
69
70 /*
71 * Process options.
72 */
73 static const RTGETOPTDEF aOpts[] =
74 {
75 { "--help", 'h', RTGETOPT_REQ_NOTHING },
76 { "--salt", 'S', RTGETOPT_REQ_STRING },
77 { "--rounds", 'R', RTGETOPT_REQ_UINT32 },
78 { "--method", 'm', RTGETOPT_REQ_STRING },
79 { "--version", 'V', RTGETOPT_REQ_NOTHING }
80 };
81
82 RTGETOPTSTATE GetState;
83 int rc = RTGetOptInit(&GetState, argc, argv, aOpts, RT_ELEMENTS(aOpts), 1 /*idxFirst*/, 0 /*fFlags - must not sort! */);
84 AssertRCReturn(rc, RTEXITCODE_INIT);
85
86 const char *pszKey = NULL;
87 const char *pszSalt = NULL;
88 uint32_t cRounds = RT_SHACRYPT_ROUNDS_DEFAULT;
89 RTMKPASSWDMETHOD enmMethod = RTMKPASSWDMETHOD_SHA512; /* Go with strongest by default. */
90
91 int ch;
92 RTGETOPTUNION ValueUnion;
93 while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0)
94 {
95 switch (ch)
96 {
97 case 'S':
98 {
99 if (!pszSalt)
100 pszSalt = ValueUnion.psz;
101 else
102 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Salt already specified!\n");
103 break;
104 }
105
106 case 'R':
107 {
108 cRounds = ValueUnion.u32;
109 if (cRounds < RT_SHACRYPT_ROUNDS_DEFAULT)
110 RTMsgWarning("Using less rounds than the default (%u) isn't a good idea!!\n",
111 RT_SHACRYPT_ROUNDS_DEFAULT);
112 break;
113 }
114
115 case 'm':
116 {
117 const char *pszMethod = ValueUnion.psz;
118 if (!RTStrICmp(pszMethod, "sha256"))
119 enmMethod = RTMKPASSWDMETHOD_SHA256;
120 else if (!RTStrICmp(pszMethod, "sha512"))
121 enmMethod = RTMKPASSWDMETHOD_SHA512;
122 else if (!RTStrICmp(pszMethod, "help"))
123 {
124 RTPrintf("Supported methods: sha256, sha512\n");
125 }
126 else
127 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Sorry, method '%s' not implemented yet!\n", pszMethod);
128 break;
129 }
130
131 case 'h':
132 {
133 RTPrintf("Usage: %s [options] password\n"
134 "\n"
135 "Options:\n"
136 " -S <salt>, --salt <salt>\n"
137 " Salt to use.\n"
138 " -R, --rounds\n"
139 " Number of rounds to use.\n"
140 " -m <type>, --method <type>\n"
141 " Method to use for creation. sha512 is the default.\n"
142 " If <type> is 'help', then the list of all available methods are printed.\n"
143 " -h, --help\n"
144 " This help screen.\n"
145 , argv[0]);
146 return RTEXITCODE_SUCCESS;
147 }
148
149 case 'V':
150 RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
151 return RTEXITCODE_SUCCESS;
152
153 case VINF_GETOPT_NOT_OPTION:
154 {
155 if (!pszKey)
156 pszKey = ValueUnion.psz;
157 else
158 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Password already specified!\n");
159 break;
160 }
161
162 default:
163 return RTGetOptPrintError(ch, &ValueUnion);
164 }
165 }
166
167 if (!pszKey)
168 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "No password specified!\n");
169
170 char szSalt[RT_SHACRYPT_SALT_MAX_LEN + 1];
171 if (!pszSalt)
172 {
173 int vrc2 = RTCrShaCryptGenerateSalt(szSalt, RT_SHACRYPT_SALT_MAX_LEN);
174 AssertRCReturn(vrc2, RTEXITCODE_FAILURE);
175 pszSalt = szSalt;
176 }
177 else if (strlen(pszSalt) < RT_SHACRYPT_SALT_MIN_LEN)
178 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Salt is too short (must be at least %u characters)!\n",
179 RT_SHACRYPT_SALT_MIN_LEN);
180 else if (strlen(pszSalt) > RT_SHACRYPT_SALT_MAX_LEN)
181 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Salt is too long (must be less or equal than %u characters)!\n",
182 RT_SHACRYPT_SALT_MAX_LEN);
183
184 /*
185 * Do the work.
186 */
187 char szResult[RT_SHACRYPT_512_MAX_SIZE];
188 switch (enmMethod)
189 {
190 case RTMKPASSWDMETHOD_SHA256:
191 rc = RTCrShaCrypt256(pszKey, pszSalt, cRounds, szResult, sizeof(szResult));
192 break;
193
194 case RTMKPASSWDMETHOD_SHA512:
195 rc = RTCrShaCrypt512(pszKey, pszSalt, cRounds, szResult, sizeof(szResult));
196 break;
197
198 default:
199 AssertFailedStmt(rc = VERR_INTERNAL_ERROR_3);
200 break;
201 }
202
203 if (RT_SUCCESS(rc))
204 RTPrintf("%s\n", szResult);
205 else
206 RTMsgError("Failed with %Rrc\n", rc);
207
208 return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
209}
210
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette