diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2016-10-27 19:39:39 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2016-10-27 19:39:39 (GMT) |
commit | ea28451286d3ea4a772fa174483f9a7a66bb1ab3 (patch) | |
tree | 6ee9d8a7848333a7ceeee3b13d492e40225f8b86 /tcllib/modules/md5crypt | |
parent | b5ca09bae0d6a1edce939eea03594dd56383f2c8 (diff) | |
parent | 7c621da28f07e449ad90c387344f07a453927569 (diff) | |
download | blt-ea28451286d3ea4a772fa174483f9a7a66bb1ab3.zip blt-ea28451286d3ea4a772fa174483f9a7a66bb1ab3.tar.gz blt-ea28451286d3ea4a772fa174483f9a7a66bb1ab3.tar.bz2 |
Merge commit '7c621da28f07e449ad90c387344f07a453927569' as 'tcllib'
Diffstat (limited to 'tcllib/modules/md5crypt')
-rw-r--r-- | tcllib/modules/md5crypt/ChangeLog | 130 | ||||
-rw-r--r-- | tcllib/modules/md5crypt/md5crypt.bench | 46 | ||||
-rw-r--r-- | tcllib/modules/md5crypt/md5crypt.man | 85 | ||||
-rw-r--r-- | tcllib/modules/md5crypt/md5crypt.tcl | 152 | ||||
-rw-r--r-- | tcllib/modules/md5crypt/md5crypt.test | 152 | ||||
-rw-r--r-- | tcllib/modules/md5crypt/md5cryptc.tcl | 174 | ||||
-rw-r--r-- | tcllib/modules/md5crypt/pkgIndex.tcl | 3 |
7 files changed, 742 insertions, 0 deletions
diff --git a/tcllib/modules/md5crypt/ChangeLog b/tcllib/modules/md5crypt/ChangeLog new file mode 100644 index 0000000..ea070bd --- /dev/null +++ b/tcllib/modules/md5crypt/ChangeLog @@ -0,0 +1,130 @@ +2013-02-01 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.15 ======================== + * + +2011-12-13 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.14 ======================== + * + +2011-01-24 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.13 ======================== + * + +2009-12-07 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.12 ======================== + * + +2009-05-07 Pat Thoyts <patthoyts@users.sourceforge.net> + + * md5cryptc.tcl: Fixed poor idiom setting interp result. + +2008-12-12 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.11.1 ======================== + * + +2008-10-16 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.11 ======================== + * + +2008-01-26 Pat Thoyts <patthoyts@users.sourceforge.net> + + * md5crypt.tcl: Implemented FR #1824212 from Aaron Faupell to + * md5crypt.man: provide a salt command for use when generating + * pkgIndex.tcl: passwords. + +2007-09-12 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.10 ======================== + * + +2007-03-21 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * md5crypt.man: Fixed all warnings due to use of now deprecated + commands. Added a section about how to give feedback. + +2006-10-03 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.9 ======================== + * + +2006-09-16 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * md5crypt.test: The critcl implementation of md5crypt generates + different error messages when called with the wrong number of + arguments. Updated the tests to take this into account. + +2006-01-23 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * md5crypt.test: More boilerplate simplified via use of test support. + +2006-01-19 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * md5crypt.test: Hooked into the new common test support code. + +2005-10-24 Andreas Kupries <andreask@activestate.com> + + * md5crypt.bench: New file. Basic benchmarks for MD5 password + hashes. + +2005-10-06 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.8 ======================== + * + +2005-10-05 Pat Thoyts <patthoyts@users.sourceforge.net> + + * md5cryptc.tcl: Fix for building with msvc. + +2004-10-05 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.7 ======================== + * + +2004-05-23 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.6.1 ======================== + * + +2004-02-15 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.6 ======================== + * + +2004-02-12 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * md5crypt.test: Testsuite fixed. Had to account that error + messages can dependent on the version of the Tcl core. + +2003-07-26 Pat Thoyts <patthoyts@users.sourceforge.net> + + * md5crypt.tcl: Provided implementation of the Apache + * md5cryptc.tcl: variation of md5crypt - as used in the + * md5crypt.test: Apache2 htpasswd program. + + * md5crypt.man: Added a manual page. + +2003-07-26 Pat Thoyts <patthoyts@users.sourceforge.net> + + * md5crypt.tcl: Initial version of a pure-Tcl and + * md5crypt.test: critcl-enhanced implementation of + * md5cryptc.tcl: the BSD MD5-crypt algorithm. + * pkgIndex.tcl: + * ChangeLog: diff --git a/tcllib/modules/md5crypt/md5crypt.bench b/tcllib/modules/md5crypt/md5crypt.bench new file mode 100644 index 0000000..6135395 --- /dev/null +++ b/tcllib/modules/md5crypt/md5crypt.bench @@ -0,0 +1,46 @@ +# -*- tcl -*- +# Tcl Benchmark File +# +# This file contains a number of benchmarks for the 'md5' module. +# This allow developers to monitor/gauge/track package performance. +# +# (c) 2005 Andreas Kupries <andreas_kupries@users.sourceforge.net> + +# We need at least version 8.2 for the package and thus the +# benchmarks. + +if {![package vsatisfies [package provide Tcl] 8.2]} { + return +} + +# ### ### ### ######### ######### ######### ########################### +## Setting up the environment ... + +set moddir [file dirname [file dirname [info script]]] +lappend auto_path $moddir + +package forget md5 +catch {namespace delete ::md5} +source [file join [file dirname [file dirname [info script]]] md5 md5x.tcl] + +package forget md5crypt +catch {namespace delete ::md5crypt} +source [file join [file dirname [info script]] md5crypt.tcl] + +set key aaaaaaaaa + +# ### ### ### ######### ######### ######### ########################### +## Benchmarks. + +foreach n {1 10 100 1000 10000} { + # Extremely expensive. Limit #iterations to keep total runtime acceptable. + + bench -desc "MD5Crypt $n" -pre { + set str [string repeat " " $n] + } -body { + md5crypt::md5crypt $key $str + } -iters 10 +} + +# ### ### ### ######### ######### ######### ########################### +## Complete diff --git a/tcllib/modules/md5crypt/md5crypt.man b/tcllib/modules/md5crypt/md5crypt.man new file mode 100644 index 0000000..c7b46f9 --- /dev/null +++ b/tcllib/modules/md5crypt/md5crypt.man @@ -0,0 +1,85 @@ +[manpage_begin md5crypt n 1.1.0] +[see_also md5] +[keywords hashing] +[keywords md5] +[keywords md5crypt] +[keywords message-digest] +[keywords security] +[moddesc {MD5-based password encryption}] +[copyright {2003, Pat Thoyts <patthoyts@users.sourceforge.net>}] +[titledesc {MD5-based password encryption}] +[category {Hashes, checksums, and encryption}] +[require Tcl 8.2] +[require md5 2.0] +[require md5crypt [opt 1.1.0]] +[description] +[para] + +This package provides an implementation of the MD5-crypt password +encryption algorithm as pioneered by FreeBSD and currently in use as a +replacement for the unix crypt(3) function in many modern +systems. An implementation of the closely related Apache MD5-crypt is +also available. + +The output of these commands are compatible with the BSD and OpenSSL +implementation of md5crypt and the Apache 2 htpasswd program. + +[section {COMMANDS}] + +[list_begin definitions] + +[call [cmd "::md5crypt::md5crypt"] \ + [arg "password"] \ + [arg "salt"]] + +Generate a BSD compatible md5-encoded password hash from the plaintext +password and a random salt (see SALT). + +[call [cmd "::md5crypt::aprcrypt"] \ + [arg "password"] \ + [arg "salt"]] + +Generate an Apache compatible md5-encoded password hash from the plaintext +password and a random salt (see SALT). + +[call [cmd "::md5crypt::salt"] [opt [arg "length"]]] + +Generate a random salt string suitable for use with the [cmd md5crypt] and +[cmd aprcrypt] commands. + +[list_end] + +[section {SALT}] + +The salt passed to either of the encryption schemes implemented here +is checked to see if it begins with the encryption scheme magic string +(either "$1$" for MD5-crypt or "$apr1$" for Apache crypt). If so, this +is removed. The remaining characters up to the next $ and up to a +maximum of 8 characters are then used as the salt. The salt text +should probably be restricted the set of ASCII alphanumeric characters +plus "./" (dot and forward-slash) - this is to preserve maximum +compatability with the unix password file format. +[para] +If a password is being generated rather than checked from a password +file then the [cmd salt] command may be used to generate a random salt. + +[section {EXAMPLES}] + +[example { +% md5crypt::md5crypt password 01234567 +$1$01234567$b5lh2mHyD2PdJjFfALlEz1 +}] + +[example { +% md5crypt::aprcrypt password 01234567 +$apr1$01234567$IXBaQywhAhc0d75ZbaSDp/ +}] + +[example { +% md5crypt::md5crypt password [md5crypt::salt] +$1$dFmvyRmO$T.V3OmzqeEf3hqJp2WFcb. +}] + +[vset CATEGORY md5crypt] +[include ../doctools2base/include/feedback.inc] +[manpage_end] diff --git a/tcllib/modules/md5crypt/md5crypt.tcl b/tcllib/modules/md5crypt/md5crypt.tcl new file mode 100644 index 0000000..47d9a0a --- /dev/null +++ b/tcllib/modules/md5crypt/md5crypt.tcl @@ -0,0 +1,152 @@ +# md5crypt.tcl - Copyright (C) 2003 Pat Thoyts <patthoyts@users.sourceforge.net> +# +# This file provides a pure tcl implementation of the BSD MD5 crypt algorithm. +# The implementation is based upon the OpenBSD code which is in turn based upon +# the original code by Poul-Henning Kamp. +# +# ------------------------------------------------------------------------- +# See the file "license.terms" for information on usage and redistribution +# of this file, and for a DISCLAIMER OF ALL WARRANTIES. +# ------------------------------------------------------------------------- +# @mdgen EXCLUDE: md5cryptc.tcl + +package require Tcl 8.2; # tcl minimum version +package require md5 2; # tcllib 1.5 + +# Try and load a compiled extension to help. +if {[catch {package require tcllibc}]} { + catch {package require md5cryptc} +} + +namespace eval md5crypt { + variable itoa64 \ + {./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz} + + namespace import -force ::md5::MD5Init ::md5::MD5Update ::md5::MD5Final + namespace export md5crypt +} + +proc ::md5crypt::to64_tcl {v n} { + variable itoa64 + for {} {$n > 0} {incr n -1} { + set i [expr {$v & 0x3f}] + append s [string index $itoa64 $i] + set v [expr {($v >> 6) & 0x3FFFFFFF}] + } + return $s +} + +# ::md5crypt::salt -- +# Generate a salt string suitable for use with the md5crypt command. +proc ::md5crypt::salt {{len 8}} { + variable itoa64 + set salt "" + for {set n 0} {$n < $len} {incr n} { + append salt [string index $itoa64 [expr {int(rand() * 64)}]] + } + return $salt +} + +proc ::md5crypt::md5crypt_tcl {magic pw salt} { + set sp 0 + + set start 0 + if {[string match "${magic}*" $salt]} { + set start [string length $magic] + } + set end [string first $ $salt $start] + if {$end < 0} {set end [string length $salt]} else {incr end -1} + if {$end - $start > 7} {set end [expr {$start + 7}]} + set salt [string range $salt $start $end] + + set ctx [MD5Init] + MD5Update $ctx $pw + MD5Update $ctx $magic + MD5Update $ctx $salt + + set ctx2 [MD5Init] + MD5Update $ctx2 $pw + MD5Update $ctx2 $salt + MD5Update $ctx2 $pw + set H2 [MD5Final $ctx2] + + for {set pl [string length $pw]} {$pl > 0} {incr pl -16} { + set tl [expr {($pl > 16 ? 16 : $pl) - 1}] + MD5Update $ctx [string range $H2 0 $tl] + } + + for {set i [string length $pw]} {$i != 0} {set i [expr {$i >> 1}]} { + if {$i & 1} { + set c \0 + } else { + set c [string index $pw 0] + } + MD5Update $ctx $c + } + + set result "${magic}${salt}\$" + + set H [MD5Final $ctx] + + for {set i 0} {$i < 1000} {incr i} { + set ctx [MD5Init] + if {$i & 1} { + MD5Update $ctx $pw + } else { + MD5Update $ctx $H + } + if {$i % 3} { + MD5Update $ctx $salt + } + if {$i % 7} { + MD5Update $ctx $pw + } + if {$i & 1} { + MD5Update $ctx $H + } else { + MD5Update $ctx $pw + } + set H [MD5Final $ctx] + } + + binary scan $H c* Vs + foreach v $Vs {lappend V [expr {$v & 0xFF}]} + set l [expr {([lindex $V 0] << 16) | ([lindex $V 6] << 8) | [lindex $V 12]}] + append result [to64 $l 4] + set l [expr {([lindex $V 1] << 16) | ([lindex $V 7] << 8) | [lindex $V 13]}] + append result [to64 $l 4] + set l [expr {([lindex $V 2] << 16) | ([lindex $V 8] << 8) | [lindex $V 14]}] + append result [to64 $l 4] + set l [expr {([lindex $V 3] << 16) | ([lindex $V 9] << 8) | [lindex $V 15]}] + append result [to64 $l 4] + set l [expr {([lindex $V 4] << 16) | ([lindex $V 10] << 8) | [lindex $V 5]}] + append result [to64 $l 4] + set l [expr {[lindex $V 11]}] + append result [to64 $l 2] + + return $result +} + +if {[info commands ::md5crypt::to64_c] == {}} { + interp alias {} ::md5crypt::to64 {} ::md5crypt::to64_tcl +} else { + interp alias {} ::md5crypt::to64 {} ::md5crypt::to64_c +} + +if {[info commands ::md5crypt::md5crypt_c] == {}} { + interp alias {} ::md5crypt::md5crypt {} ::md5crypt::md5crypt_tcl {$1$} + interp alias {} ::md5crypt::aprcrypt {} ::md5crypt::md5crypt_tcl {$apr1$} +} else { + interp alias {} ::md5crypt::md5crypt {} ::md5crypt::md5crypt_c {$1$} + interp alias {} ::md5crypt::aprcrypt {} ::md5crypt::md5crypt_c {$apr1$} +} + +# ------------------------------------------------------------------------- + +package provide md5crypt 1.1.0 + +# ------------------------------------------------------------------------- +# Local Variables: +# mode: tcl +# indent-tabs-mode: nil +# End: diff --git a/tcllib/modules/md5crypt/md5crypt.test b/tcllib/modules/md5crypt/md5crypt.test new file mode 100644 index 0000000..5ae8aca --- /dev/null +++ b/tcllib/modules/md5crypt/md5crypt.test @@ -0,0 +1,152 @@ +# -*- tcl -*- +# md5crypt.test: tests for the md5crypt commands +# +# This file contains a collection of tests for one or more of the Tcllib +# commands. Sourcing this file into Tcl runs the tests and generates +# output for errors. No output means no errors were found. +# +# Copyright (C) 2003 Pat Thoyts <patthoyts@users.sourceforge.net> +# +# RCS: @(#) $Id: md5crypt.test,v 1.9 2006/10/09 21:41:41 andreas_kupries Exp $ + +# ------------------------------------------------------------------------- + +source [file join \ + [file dirname [file dirname [file join [pwd] [info script]]]] \ + devtools testutilities.tcl] + +testsNeedTcl 8.2 +testsNeedTcltest 1.0 + +testing { + useLocal md5crypt.tcl md5crypt +} + +# ------------------------------------------------------------------------- +# Setup any constraints + +# Set this true if we have the critcl version. + +::tcltest::testConstraint md5crypt_c \ + [llength [info commands ::md5crypt::md5crypt_c]] + +# ------------------------------------------------------------------------- + +if {[llength [info commands ::md5crypt::md5crypt_c]]} { + puts "> critcl based" + set impl critcl +} else { + puts "> pure Tcl" + set impl tcl +} + +# ------------------------------------------------------------------------- +# Now the package specific tests.... +# ------------------------------------------------------------------------- +# A procedure and a C command generate different error messages. + +test md5crypt-1.0 {md5crypt basic usage} { + catch {::md5crypt::md5crypt} result + if {$impl == "critcl"} { + set expected {wrong # args: should be "::md5crypt::md5crypt_c magic pw salt"} + } else { + set expected [tcltest::wrongNumArgs {*} {pw salt} 0] + } + string match $expected $result +} 1 + +test md5crypt-1.1 {md5crypt basic usage} { + catch {::md5crypt::md5crypt pw} result + if {$impl == "critcl"} { + set expected {wrong # args: should be "::md5crypt::md5crypt_c magic pw salt"} + } else { + set expected [tcltest::wrongNumArgs {*} {pw salt} 1] + } + string match $expected $result +} 1 + +test md5crypt-1.2 {md5crypt basic usage} { + catch {::md5crypt::md5crypt pw salt other} result + if {$impl == "critcl"} { + set expected {wrong # args: should be "::md5crypt::md5crypt_c magic pw salt"} + } else { + set expected [tcltest::tooManyArgs {*} {pw salt}] + } + string match $expected $result +} 1 + +# ------------------------------------------------------------------------- + +foreach {n salt passwd expected} { + 1 {} a {$1$$Ij31LCAysPM23KuPlm1wA/} + 2 {a} a {$1$a$44cUw6Nm5bX0muHWNIwub0} + 3 {aa} a {$1$aa$aM/8fu5RTEKSCJWsk9qH.0} + 4 {aaa} a {$1$aaa$SCk4CXyogLtcfwl2VqfSF0} + 5 {aaaa} a {$1$aaaa$tjZedp/Ch2UpwkJdEKLPm.} + 6 {aaaaa} a {$1$aaaaa$iVkHUcCwuXWk4NaYTbyUa/} + 7 {aaaaaa} a {$1$aaaaaa$MUMWPbGfzrHFCNm7ZHg31.} + 8 {aaaaaaa} a {$1$aaaaaaa$4OzJTk7W1gmppy.1Lu4nr.} + 9 {aaaaaaaa} a {$1$aaaaaaaa$S270EsVIz5M8Y9/k4SSEf.} + 10 {aaaaaaaaa} a {$1$aaaaaaaa$S270EsVIz5M8Y9/k4SSEf.} + 12 {a$aaaaaaa} a {$1$a$44cUw6Nm5bX0muHWNIwub0} + 13 {$1$a$junk} a {$1$a$44cUw6Nm5bX0muHWNIwub0} +} { + test md5passwd-2.${n} [list md5crypt salt check \"$salt\"] { + ::md5crypt::md5crypt $passwd $salt + } $expected + + # If the C code is loaded, then we have tested that so now check the + # pure-tcl implementation as well. + test md5passwd-3.${n}_tcl [list md5crypt salt check \"$salt\"] \ + {md5crypt_c} { + ::md5crypt::md5crypt_tcl {$1$} $passwd $salt + } $expected +} + +# ------------------------------------------------------------------------- + +foreach {n salt passwd expected} [list \ + 1 {a} {} {$1$a$8CfZSfErbeskipdhZHtvu.} \ + 2 {a} {a} {$1$a$44cUw6Nm5bX0muHWNIwub0} \ + 3 {a} [string repeat a 100] {$1$a$vTAcWEblAgdUlX6KBz0NM.} \ + 4 {a} [string repeat a 200] {$1$a$kC.K4D6mvUznpkjWJK8Tm0} \ + 5 {a} [string repeat a 400] {$1$a$nBvNVTsAryOnHlW7L/gzf/} \ + 6 {a} [string repeat a 1000] {$1$a$yhNnTV4IKHbl8oEB/eJaj0} \ +] { + test md5passwd-4.${n} {md5crypt check passwd} { + ::md5crypt::md5crypt $passwd $salt + } $expected + + # If the C code is loaded, then we have tested that so now check the + # pure-tcl implementation as well. + test md5passwd-5.${n}_tcl {md5crypt (pure-Tcl) check passwd} {md5crypt_c} { + ::md5crypt::md5crypt_tcl {$1$} $passwd $salt + } $expected +} + +# ------------------------------------------------------------------------- + +foreach {n salt passwd expected} [list \ + 1 {883.....} {a} {$apr1$883.....$wCU4E7Fv9tHAzFEm5D.mp/} \ + 2 {XA3.....} {a} {$apr1$XA3.....$kp5j/oX/OCrpKdKhmUqTu1} \ +] { + test md5passwd-6.${n} {aprcrypt check passwd} { + ::md5crypt::aprcrypt $passwd $salt + } $expected + + # If the C code is loaded, then we have tested that so now check the + # pure-tcl implementation as well. + test md5passwd-7.${n}_tcl {aprcrypt (pure-Tcl) check passwd} {md5crypt_c} { + ::md5crypt::md5crypt_tcl {$apr1$} $passwd $salt + } $expected +} + +# ------------------------------------------------------------------------- + +testsuiteCleanup + +# ------------------------------------------------------------------------- +# Local variables: +# mode: tcl +# indent-tabs-mode: nil +# End:
\ No newline at end of file diff --git a/tcllib/modules/md5crypt/md5cryptc.tcl b/tcllib/modules/md5crypt/md5cryptc.tcl new file mode 100644 index 0000000..e1facd8 --- /dev/null +++ b/tcllib/modules/md5crypt/md5cryptc.tcl @@ -0,0 +1,174 @@ +# md5cryptc.tcl - Copyright (C) 2003 Pat Thoyts <patthoyts@users.sourceforge.net> +# +# This is a critcl-based wrapper to provide a Tcl implementation of the md5crypt +# function. The C code here is based upon the OpenBSD source, which is in turn +# derived from the original implementation by Poul-Henning Kamp +# +# The original C source license reads: +#/* +# * ---------------------------------------------------------------------------- +# * "THE BEER-WARE LICENSE" (Revision 42): +# * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you +# * can do whatever you want with this stuff. If we meet some day, and you think +# * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp +# * ---------------------------------------------------------------------------- +# */ +# +# ------------------------------------------------------------------------- +# See the file "license.terms" for information on usage and redistribution +# of this file, and for a DISCLAIMER OF ALL WARRANTIES. +# ------------------------------------------------------------------------- + + +package require critcl +# @sak notprovided md5cryptc +package provide md5cryptc 1.0 + +critcl::cheaders ../md5/md5.h +#critcl::csources ../md5/md5.c + +namespace eval ::md5crypt { + critcl::ccode { +#include <string.h> +#include "md5.h" +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + static unsigned char itoa64[] = + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + static void to64(char *s, unsigned int v, int n) + { + while (--n >= 0) { + *s++ = itoa64[v&0x3f]; + v >>= 6; + } + } + + static void dump(const char *s, unsigned int len) + { + unsigned int i; + for (i = 0; i < len; i++) + printf("%02X", s[i]&0xFF); + putchar('\n'); + } + + static char * md5crypt(const char *pw, + const char *salt, + const char *magic) + { + static char passwd[120], *p; + static const unsigned char *sp,*ep; + unsigned char final[16]; + int sl,pl,i; + MD5_CTX ctx,ctx1; + unsigned long l; + + /* Refine the Salt first */ + sp = (const unsigned char *)salt; + + /* If it starts with the magic string, then skip that */ + if(!strncmp((const char *)sp,(const char *)magic,strlen((const char *)magic))) + sp += strlen((const char *)magic); + + /* It stops at the first '$', max 8 chars */ + for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++) + continue; + + /* get the length of the true salt */ + sl = ep - sp; + + MD5Init(&ctx); + + /* The password first, since that is what is most unknown */ + MD5Update(&ctx,(unsigned char *)pw,strlen(pw)); + + /* Then our magic string */ + MD5Update(&ctx,(unsigned char *)magic,strlen((const char *)magic)); + + /* Then the raw salt */ + MD5Update(&ctx,(unsigned char*)sp,sl); + + /* Then just as many characters of the MD5(pw,salt,pw) */ + MD5Init(&ctx1); + MD5Update(&ctx1,(unsigned char *)pw,strlen(pw)); + MD5Update(&ctx1,(unsigned char *)sp,sl); + MD5Update(&ctx1,(unsigned char *)pw,strlen(pw)); + MD5Final(final,&ctx1); + + for(pl = strlen(pw); pl > 0; pl -= 16) { + int tl = pl > 16 ? 16 : pl; + MD5Update(&ctx,final,pl>16 ? 16 : pl); + } + + /* Don't leave anything around in vm they could use. */ + memset(final,0,sizeof final); + + /* Then something really weird... */ + for (i = strlen(pw); i ; i >>= 1) { + if(i&1) + MD5Update(&ctx, final, 1); + else + MD5Update(&ctx, (unsigned char *)pw, 1); + } + + /* Now make the output string */ + snprintf(passwd, sizeof(passwd), "%s%.*s$", (char *)magic, + sl, (const char *)sp); + + MD5Final(final,&ctx); + + /* + * and now, just to make sure things don't run too fast + * On a 60 Mhz Pentium this takes 34 msec, so you would + * need 30 seconds to build a 1000 entry dictionary... + */ + for(i=0;i<1000;i++) { + MD5Init(&ctx1); + if(i & 1) + MD5Update(&ctx1,(unsigned char *)pw,strlen(pw)); + else + MD5Update(&ctx1,final,16); + + if(i % 3) + MD5Update(&ctx1,(unsigned char *)sp,sl); + + if(i % 7) + MD5Update(&ctx1,(unsigned char *)pw,strlen(pw)); + + if(i & 1) + MD5Update(&ctx1,final,16); + else + MD5Update(&ctx1,(unsigned char *)pw,strlen(pw)); + MD5Final(final,&ctx1); + } + + p = passwd + strlen(passwd); + + l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4; + l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4; + l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4; + l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4; + l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4; + l = final[11] ; to64(p,l,2); p += 2; + *p = '\0'; + + /* Don't leave anything around in vm they could use. */ + memset(final,0,sizeof final); + + return passwd; + } + } + critcl::cproc to64_c {Tcl_Interp* interp int v int n} ok { + char s[5]; + to64(s, (unsigned int)v, n); + Tcl_SetObjResult(interp, Tcl_NewStringObj(s, n)); + return TCL_OK; + } + + critcl::cproc md5crypt_c {Tcl_Interp* interp char* magic char* pw char* salt} ok { + char* s = md5crypt(pw, salt, magic); + Tcl_SetObjResult(interp, Tcl_NewStringObj(s, strlen(s))); + return TCL_OK; + } +} diff --git a/tcllib/modules/md5crypt/pkgIndex.tcl b/tcllib/modules/md5crypt/pkgIndex.tcl new file mode 100644 index 0000000..487ff9d --- /dev/null +++ b/tcllib/modules/md5crypt/pkgIndex.tcl @@ -0,0 +1,3 @@ +# package index for md5crypt +if {![package vsatisfies [package provide Tcl] 8.2]} {return} +package ifneeded md5crypt 1.1.0 [list source [file join $dir md5crypt.tcl]] |