1 /* $NetBSD: cksum.c,v 1.31 2005/09/24 22:40:32 elad Exp $ */ 2 3 /*- 4 * Copyright (c) 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * James W. Williams of NASA Goddard Space Flight Center. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 /*- 36 * Copyright (c) 1997 Jason R. Thorpe. All rights reserved. 37 * 38 * This code is derived from software contributed to Berkeley by 39 * James W. Williams of NASA Goddard Space Flight Center. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 3. All advertising materials mentioning features or use of this software 50 * must display the following acknowledgement: 51 * This product includes software developed by the University of 52 * California, Berkeley and its contributors. 53 * 4. Neither the name of the University nor the names of its contributors 54 * may be used to endorse or promote products derived from this software 55 * without specific prior written permission. 56 * 57 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67 * SUCH DAMAGE. 68 */ 69 70 #if HAVE_NBTOOL_CONFIG_H 71 #include "nbtool_config.h" 72 #endif 73 74 #include <sys/cdefs.h> 75 #if defined(__COPYRIGHT) && !defined(lint) 76 __COPYRIGHT("@(#) Copyright (c) 1991, 1993\n\ 77 The Regents of the University of California. All rights reserved.\n"); 78 #endif /* not lint */ 79 80 #if defined(__RCSID) && !defined(lint) 81 #if 0 82 static char sccsid[] = "@(#)cksum.c 8.2 (Berkeley) 4/28/95"; 83 #endif 84 __RCSID("$NetBSD: cksum.c,v 1.31 2005/09/24 22:40:32 elad Exp $"); 85 #endif /* not lint */ 86 87 #include <sys/cdefs.h> 88 #include <sys/types.h> 89 90 #include <err.h> 91 #include <errno.h> 92 #include <fcntl.h> 93 #include <locale.h> 94 #include <md5.h> 95 #include <md4.h> 96 #include <md2.h> 97 #include <sha1.h> 98 #include <crypto/sha2.h> 99 #include <crypto/rmd160.h> 100 #include <stdio.h> 101 #include <stdlib.h> 102 #include <string.h> 103 #include <unistd.h> 104 105 #include "extern.h" 106 107 #define HASH_MD2 0 108 #define HASH_MD4 1 109 #define HASH_MD5 2 110 #define HASH_SHA1 3 111 #define HASH_RMD160 4 112 113 typedef char *(*_filefunc)(const char *, char *); 114 115 struct hash { 116 const char *progname; 117 const char *hashname; 118 void (*stringfunc)(const char *); 119 void (*timetrialfunc)(void); 120 void (*testsuitefunc)(void); 121 void (*filterfunc)(int); 122 char *(*filefunc)(const char *, char *); 123 } hashes[] = { 124 { "md2", "MD2", 125 MD2String, MD2TimeTrial, MD2TestSuite, 126 MD2Filter, MD2File }, 127 { "md4", "MD4", 128 MD4String, MD4TimeTrial, MD4TestSuite, 129 MD4Filter, MD4File }, 130 { "md5", "MD5", 131 MD5String, MD5TimeTrial, MD5TestSuite, 132 MD5Filter, MD5File }, 133 { "sha1", "SHA1", 134 SHA1String, SHA1TimeTrial, SHA1TestSuite, 135 SHA1Filter, (_filefunc) SHA1File }, 136 { "rmd160", "RMD160", 137 RMD160String, RMD160TimeTrial, RMD160TestSuite, 138 RMD160Filter, (_filefunc) RMD160File }, 139 { "sha256", "SHA256", 140 SHA256_String, SHA256_TimeTrial, SHA256_TestSuite, 141 SHA256_Filter, (_filefunc) SHA256_File }, 142 { "sha384", "SHA384", 143 SHA384_String, SHA384_TimeTrial, SHA384_TestSuite, 144 SHA384_Filter, (_filefunc) SHA384_File }, 145 { "sha512", "SHA512", 146 SHA512_String, SHA512_TimeTrial, SHA512_TestSuite, 147 SHA512_Filter, (_filefunc) SHA512_File }, 148 { NULL } 149 }; 150 151 int hash_digest_file(char *, struct hash *, int); 152 void requirehash(const char *); 153 void usage(void); 154 155 int 156 main(int argc, char **argv) 157 { 158 int ch, fd, rval, dosum, pflag, nohashstdin; 159 u_int32_t val; 160 off_t len; 161 char *fn; 162 const char *progname; 163 int (*cfncn) (int, u_int32_t *, off_t *); 164 void (*pfncn) (char *, u_int32_t, off_t); 165 struct hash *hash; 166 int normal, i; 167 168 cfncn = NULL; 169 pfncn = NULL; 170 dosum = pflag = nohashstdin = 0; 171 normal = 0; 172 173 setlocale(LC_ALL, ""); 174 175 progname = getprogname(); 176 177 for (hash = hashes; hash->hashname != NULL; hash++) 178 if (strcmp(progname, hash->progname) == 0) 179 break; 180 181 if (hash->hashname == NULL) { 182 hash = NULL; 183 184 if (!strcmp(progname, "sum")) { 185 dosum = 1; 186 cfncn = csum1; 187 pfncn = psum1; 188 } else { 189 cfncn = crc; 190 pfncn = pcrc; 191 } 192 } 193 194 /* 195 * The -1, -2, -4, -5, -6, and -m flags should be deprecated, but 196 * are still supported in code to not break anything that might 197 * be using them. 198 */ 199 while ((ch = getopt(argc, argv, "a:mno:ps:tx12456")) != -1) 200 switch(ch) { 201 case 'a': 202 if (hash != NULL || dosum) { 203 warnx("illegal use of -a option\n"); 204 usage(); 205 } 206 i = 0; 207 while (hashes[i].hashname != NULL) { 208 if (!strcasecmp(hashes[i].hashname, optarg)) { 209 hash = &hashes[i]; 210 break; 211 } 212 i++; 213 } 214 if (hash == NULL) { 215 if (!strcasecmp(optarg, "old1")) { 216 cfncn = csum1; 217 pfncn = psum1; 218 } else if (!strcasecmp(optarg, "old2")) { 219 cfncn = csum2; 220 pfncn = psum2; 221 } else if (!strcasecmp(optarg, "crc")) { 222 cfncn = crc; 223 pfncn = pcrc; 224 } else { 225 warnx("illegal argument to -a option"); 226 usage(); 227 } 228 } 229 break; 230 case '2': 231 if (dosum) { 232 warnx("sum mutually exclusive with md2"); 233 usage(); 234 } 235 hash = &hashes[HASH_MD2]; 236 break; 237 case '4': 238 if (dosum) { 239 warnx("sum mutually exclusive with md4"); 240 usage(); 241 } 242 hash = &hashes[HASH_MD4]; 243 break; 244 case 'm': 245 case '5': 246 if (dosum) { 247 warnx("sum mutually exclusive with md5"); 248 usage(); 249 } 250 hash = &hashes[HASH_MD5]; 251 break; 252 case '1': 253 if (dosum) { 254 warnx("sum mutually exclusive with sha1"); 255 usage(); 256 } 257 hash = &hashes[HASH_SHA1]; 258 break; 259 case '6': 260 if (dosum) { 261 warnx("sum mutually exclusive with rmd160"); 262 usage(); 263 } 264 hash = &hashes[HASH_RMD160]; 265 break; 266 case 'n': 267 normal = 1; 268 break; 269 case 'o': 270 if (hash) { 271 warnx("%s mutually exclusive with sum", 272 hash->hashname); 273 usage(); 274 } 275 if (!strcmp(optarg, "1")) { 276 cfncn = csum1; 277 pfncn = psum1; 278 } else if (!strcmp(optarg, "2")) { 279 cfncn = csum2; 280 pfncn = psum2; 281 } else { 282 warnx("illegal argument to -o option"); 283 usage(); 284 } 285 break; 286 case 'p': 287 if (hash == NULL) 288 requirehash("-p"); 289 pflag = 1; 290 break; 291 case 's': 292 if (hash == NULL) 293 requirehash("-s"); 294 nohashstdin = 1; 295 hash->stringfunc(optarg); 296 break; 297 case 't': 298 if (hash == NULL) 299 requirehash("-t"); 300 nohashstdin = 1; 301 hash->timetrialfunc(); 302 break; 303 case 'x': 304 if (hash == NULL) 305 requirehash("-x"); 306 nohashstdin = 1; 307 hash->testsuitefunc(); 308 break; 309 case '?': 310 default: 311 usage(); 312 } 313 argc -= optind; 314 argv += optind; 315 316 fd = STDIN_FILENO; 317 fn = NULL; 318 rval = 0; 319 do { 320 if (*argv) { 321 fn = *argv++; 322 if (hash != NULL) { 323 if (hash_digest_file(fn, hash, normal)) { 324 warn("%s", fn); 325 rval = 1; 326 } 327 continue; 328 } 329 if ((fd = open(fn, O_RDONLY, 0)) < 0) { 330 warn("%s", fn); 331 rval = 1; 332 continue; 333 } 334 } else if (hash && !nohashstdin) { 335 hash->filterfunc(pflag); 336 } 337 338 if (hash == NULL) { 339 if (cfncn(fd, &val, &len)) { 340 warn("%s", fn ? fn : "stdin"); 341 rval = 1; 342 } else 343 pfncn(fn, val, len); 344 (void)close(fd); 345 } 346 } while (*argv); 347 exit(rval); 348 } 349 350 int 351 hash_digest_file(char *fn, struct hash *hash, int normal) 352 { 353 char *cp; 354 355 cp = hash->filefunc(fn, NULL); 356 if (cp == NULL) 357 return 1; 358 359 if (normal) 360 printf("%s %s\n", cp, fn); 361 else 362 printf("%s (%s) = %s\n", hash->hashname, fn, cp); 363 364 free(cp); 365 366 return 0; 367 } 368 369 void 370 requirehash(const char *flg) 371 { 372 warnx("%s flag requires `md2', `md4', `md5', `sha1', or `rmd160'", 373 flg); 374 usage(); 375 } 376 377 void 378 usage(void) 379 { 380 381 (void)fprintf(stderr, "usage: cksum [-n] [-m | -1 | -2 | -4 | -5 | -6 | [-o 1 | 2]] [file ...]\n"); 382 (void)fprintf(stderr, " sum [file ...]\n"); 383 (void)fprintf(stderr, 384 " md2 [-n] [-p | -t | -x | -s string] [file ...]\n"); 385 (void)fprintf(stderr, 386 " md4 [-n] [-p | -t | -x | -s string] [file ...]\n"); 387 (void)fprintf(stderr, 388 " md5 [-n] [-p | -t | -x | -s string] [file ...]\n"); 389 (void)fprintf(stderr, 390 " sha1 [-n] [-p | -t | -x | -s string] [file ...]\n"); 391 (void)fprintf(stderr, 392 " rmd160 [-n] [-p | -t | -x | -s string] [file ...]\n"); 393 exit(1); 394 } 395