View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0003090 | SOGo | Backend General | public | 2015-02-03 15:58 | 2016-05-12 15:32 |
Reporter | Bigio | Assigned To | |||
Priority | normal | Severity | minor | Reproducibility | always |
Status | new | Resolution | open | ||
Platform | OpenBSD | OS | OpenBSD | OS Version | 5.6 |
Product Version | 2.2.15 | ||||
Summary | 0003090: Unable to authenticate on OpenBSD with UserPasswordAlgotithm = md5-crypt | ||||
Description | Starting from OpenBSD 5.6 md5-crypt has been remove from crypt(3). | ||||
Tags | No tags attached. | ||||
sogo-md5crypt.diff (6,825 bytes)
--- /dev/null Tue Feb 3 16:54:26 2015 +++ SoObjects/SOGo/md5crypt.h Tue Feb 3 16:52:38 2015 @@ -0,0 +1,36 @@ +/* $OpenBSD: md5crypt.c,v 1.17 2014/04/03 15:55:29 beck Exp $ */ + +/* + * Copyright (c) 2000 Poul-Henning Kamp <phk@FreeBSD.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * If we meet some day, and you think this stuff is worth it, you + * can buy me a beer in return. Poul-Henning Kamp + */ + +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <md5.h> +#include <string.h> + +/* + * UNIX password + * + * Use MD5 for what it is best at... + */ + +char *md5crypt(const char *pw, const char *salt); --- /dev/null Tue Feb 3 16:54:31 2015 +++ SoObjects/SOGo/md5crypt.m Tue Feb 3 16:52:38 2015 @@ -0,0 +1,153 @@ +/* $OpenBSD: md5crypt.c,v 1.17 2014/04/03 15:55:29 beck Exp $ */ + +/* + * Copyright (c) 2000 Poul-Henning Kamp <phk@FreeBSD.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * If we meet some day, and you think this stuff is worth it, you + * can buy me a beer in return. Poul-Henning Kamp + */ + +#include "md5crypt.h" + +static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static void to64(char *, u_int32_t, int); + +static void +to64(char *s, u_int32_t v, int n) +{ + while (--n >= 0) { + *s++ = itoa64[v&0x3f]; + v >>= 6; + } +} + +/* + * UNIX password + * + * Use MD5 for what it is best at... + */ + +char * +md5crypt(const char *pw, const char *salt) +{ + /* + * This string is the magic for this algorithm. + * Having it this way, we can get better later on. + */ + static unsigned char *magic = (unsigned char *)"$1$"; + + static char passwd[120], *p; + static const unsigned char *sp,*ep; + unsigned char final[16]; + int sl,pl,i; + MD5_CTX ctx,ctx1; + u_int32_t 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,(const unsigned char *)pw,strlen(pw)); + + /* Then our magic string */ + MD5Update(&ctx,magic,strlen((const char *)magic)); + + /* Then the raw salt */ + MD5Update(&ctx,sp,sl); + + /* Then just as many characters of the MD5(pw,salt,pw) */ + MD5Init(&ctx1); + MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw)); + MD5Update(&ctx1,sp,sl); + MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw)); + MD5Final(final,&ctx1); + for(pl = strlen(pw); pl > 0; pl -= 16) + 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, (const 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... + * On a modern machine, with possible GPU optimization, + * this will run a lot faster than that. + */ + for(i=0;i<1000;i++) { + MD5Init(&ctx1); + if(i & 1) + MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw)); + else + MD5Update(&ctx1,final,16); + + if(i % 3) + MD5Update(&ctx1,sp,sl); + + if(i % 7) + MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw)); + + if(i & 1) + MD5Update(&ctx1,final,16); + else + MD5Update(&ctx1,(const 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; +} --- SoObjects/SOGo/NSData+Crypto.m.orig Tue Dec 30 14:08:51 2014 +++ SoObjects/SOGo/NSData+Crypto.m Tue Feb 3 16:52:24 2015 @@ -559,7 +559,11 @@ saltString = [[NSString alloc] initWithData: saltData encoding: NSUTF8StringEncoding]; +#ifdef __OpenBSD__ + buf = md5crypt([cryptString UTF8String], [saltString UTF8String]); +#else buf = crypt([cryptString UTF8String], [saltString UTF8String]); +#endif [cryptString release]; [saltString release]; if (!buf) @@ -589,6 +593,11 @@ // The salt is weak here, but who cares anyway, crypt should not // be used anymore buf = crypt([cryptString UTF8String], [saltString UTF8String]); +#ifdef __OpenBSD__ + if (!buf) { + buf = md5crypt([cryptString UTF8String], [saltString UTF8String]); + } +#endif [saltString release]; [cryptString release]; if (!buf) |
|
I think you are missing the part of the patch to the GNUmakefile ;) I'm also not 100% sure, if the #include md5crypt.h is missing, NSData+Crypto.m, don't you get a warning when compiling, for the line where md5crypt is used? |
|
sogo.diff (6,221 bytes)
--- SoObjects/SOGo/GNUmakefile.orig Tue Dec 30 14:08:51 2014 +++ SoObjects/SOGo/GNUmakefile Thu Feb 5 14:51:29 2015 @@ -86,6 +86,7 @@ @touch SOGoBuild.m SOGo_OBJC_FILES = \ + md5crypt.m \ SOGoBuild.m \ SOGoProductLoader.m \ \ --- /dev/null Thu Feb 5 14:53:27 2015 +++ SoObjects/SOGo/md5crypt.h Thu Feb 5 14:52:49 2015 @@ -0,0 +1,36 @@ +/* $OpenBSD: md5crypt.c,v 1.17 2014/04/03 15:55:29 beck Exp $ */ + +/* + * Copyright (c) 2000 Poul-Henning Kamp <phk@FreeBSD.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * If we meet some day, and you think this stuff is worth it, you + * can buy me a beer in return. Poul-Henning Kamp + */ + +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <md5.h> +#include <string.h> + +/* + * UNIX password + * + * Use MD5 for what it is best at... + */ + +char *md5crypt(const char *pw, const char *salt); --- /dev/null Thu Feb 5 14:53:30 2015 +++ SoObjects/SOGo/md5crypt.m Thu Feb 5 14:52:49 2015 @@ -0,0 +1,153 @@ +/* $OpenBSD: md5crypt.c,v 1.17 2014/04/03 15:55:29 beck Exp $ */ + +/* + * Copyright (c) 2000 Poul-Henning Kamp <phk@FreeBSD.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * If we meet some day, and you think this stuff is worth it, you + * can buy me a beer in return. Poul-Henning Kamp + */ + +#include "md5crypt.h" + +static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static void to64(char *, u_int32_t, int); + +static void +to64(char *s, u_int32_t v, int n) +{ + while (--n >= 0) { + *s++ = itoa64[v&0x3f]; + v >>= 6; + } +} + +/* + * UNIX password + * + * Use MD5 for what it is best at... + */ + +char * +md5crypt(const char *pw, const char *salt) +{ + /* + * This string is the magic for this algorithm. + * Having it this way, we can get better later on. + */ + static unsigned char *magic = (unsigned char *)"$1$"; + + static char passwd[120], *p; + static const unsigned char *sp,*ep; + unsigned char final[16]; + int sl,pl,i; + MD5_CTX ctx,ctx1; + u_int32_t 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,(const unsigned char *)pw,strlen(pw)); + + /* Then our magic string */ + MD5Update(&ctx,magic,strlen((const char *)magic)); + + /* Then the raw salt */ + MD5Update(&ctx,sp,sl); + + /* Then just as many characters of the MD5(pw,salt,pw) */ + MD5Init(&ctx1); + MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw)); + MD5Update(&ctx1,sp,sl); + MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw)); + MD5Final(final,&ctx1); + for(pl = strlen(pw); pl > 0; pl -= 16) + 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, (const 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... + * On a modern machine, with possible GPU optimization, + * this will run a lot faster than that. + */ + for(i=0;i<1000;i++) { + MD5Init(&ctx1); + if(i & 1) + MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw)); + else + MD5Update(&ctx1,final,16); + + if(i % 3) + MD5Update(&ctx1,sp,sl); + + if(i % 7) + MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw)); + + if(i & 1) + MD5Update(&ctx1,final,16); + else + MD5Update(&ctx1,(const 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; +} |
|
Full patch attached, sorry. |
|
Please adjust the patch so that: 1- the GNUmakefile only includes this if it is OpenBSD 2- make sur that it is tested on Linux too, with no compiler warning |
|
Date Modified | Username | Field | Change |
---|---|---|---|
2015-02-03 15:58 | Bigio | New Issue | |
2015-02-03 15:58 | Bigio | File Added: sogo-md5crypt.diff | |
2015-02-05 12:48 | buzzdee | Note Added: 0008139 | |
2015-02-05 13:55 | Bigio | File Added: sogo.diff | |
2015-02-05 13:55 | Bigio | Note Added: 0008141 | |
2016-05-12 15:32 | ludovic | Note Added: 0010125 |