]> jfr.im git - irc/evilnet/x3.git/commitdiff
AfterNET is working on the ability to merge mambo and authserv user accounts into...
authorrubin <redacted>
Tue, 7 Dec 2004 07:40:58 +0000 (07:40 +0000)
committerrubin <redacted>
Tue, 7 Dec 2004 07:40:58 +0000 (07:40 +0000)
adds some special hacks for a web-based registration/pass reset bot from the website, and modifies
the saved passwords to true md5 compatable (same as php uses).
Old passwords are still read, and when changed will be saved properly in the new format.  Old accounts
will not work on the website until they are updated to the new md5 format.

src/md5.c
src/md5.h
src/nickserv.c

index 189d45d85968553d69cf285cab96b79a4fe7178c..7b8edbc1e1437fb328fb9d74824f3b7654182483 100644 (file)
--- a/src/md5.c
+++ b/src/md5.c
@@ -1,3 +1,34 @@
+/*
+ *  RFC 1321 compliant MD5 implementation
+ *
+ *  Copyright (C) 2001-2003  Christophe Devine
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <string.h>
+
+#include "common.h"
+#include "md5.h"
+
+#define OLDPASSFUNC
+#ifdef OLDPASSFUNC
+/* ----------------------------------------------------- */
+/*         DELETE THIS SOME DAY - OLD STUFF HERE         */
+/* ----------------------------------------------------- */
+
 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm */
 
 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
@@ -22,9 +53,6 @@ These notices must be retained in any copies of any part of this
 documentation and/or software.
  */
 
-#include "common.h"
-#include "md5.h"
-
 /* Constants for MD5Transform routine.
  */
 #define S11 7
@@ -345,12 +373,287 @@ cryptpass_real(const char *pass, char *buffer, int seed)
     return buffer;
 }
 
+/* ----------------------------------------------------- */
+/*           DELETE ABOVE SOME DAY -- OLD STUFF          */
+/* ----------------------------------------------------- */
+
+#endif
+
+#define GET_UINT32(n,b,i)                       \
+{                                               \
+    (n) = ( (uint32) (b)[(i)    ]       )       \
+        | ( (uint32) (b)[(i) + 1] <<  8 )       \
+        | ( (uint32) (b)[(i) + 2] << 16 )       \
+        | ( (uint32) (b)[(i) + 3] << 24 );      \
+}
+
+#define PUT_UINT32(n,b,i)                       \
+{                                               \
+    (b)[(i)    ] = (uint8) ( (n)       );       \
+    (b)[(i) + 1] = (uint8) ( (n) >>  8 );       \
+    (b)[(i) + 2] = (uint8) ( (n) >> 16 );       \
+    (b)[(i) + 3] = (uint8) ( (n) >> 24 );       \
+}
+
+void md5_starts( md5_context *ctx )
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    ctx->state[0] = 0x67452301;
+    ctx->state[1] = 0xEFCDAB89;
+    ctx->state[2] = 0x98BADCFE;
+    ctx->state[3] = 0x10325476;
+}
+
+void md5_process( md5_context *ctx, uint8 data[64] )
+{
+    uint32 X[16], A, B, C, D;
+
+    GET_UINT32( X[0],  data,  0 );
+    GET_UINT32( X[1],  data,  4 );
+    GET_UINT32( X[2],  data,  8 );
+    GET_UINT32( X[3],  data, 12 );
+    GET_UINT32( X[4],  data, 16 );
+    GET_UINT32( X[5],  data, 20 );
+    GET_UINT32( X[6],  data, 24 );
+    GET_UINT32( X[7],  data, 28 );
+    GET_UINT32( X[8],  data, 32 );
+    GET_UINT32( X[9],  data, 36 );
+    GET_UINT32( X[10], data, 40 );
+    GET_UINT32( X[11], data, 44 );
+    GET_UINT32( X[12], data, 48 );
+    GET_UINT32( X[13], data, 52 );
+    GET_UINT32( X[14], data, 56 );
+    GET_UINT32( X[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define P(a,b,c,d,k,s,t)                                \
+{                                                       \
+    a += F(b,c,d) + X[k] + t; a = S(a,s) + b;           \
+}
+
+    A = ctx->state[0];
+    B = ctx->state[1];
+    C = ctx->state[2];
+    D = ctx->state[3];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+
+    P( A, B, C, D,  0,  7, 0xD76AA478 );
+    P( D, A, B, C,  1, 12, 0xE8C7B756 );
+    P( C, D, A, B,  2, 17, 0x242070DB );
+    P( B, C, D, A,  3, 22, 0xC1BDCEEE );
+    P( A, B, C, D,  4,  7, 0xF57C0FAF );
+    P( D, A, B, C,  5, 12, 0x4787C62A );
+    P( C, D, A, B,  6, 17, 0xA8304613 );
+    P( B, C, D, A,  7, 22, 0xFD469501 );
+    P( A, B, C, D,  8,  7, 0x698098D8 );
+    P( D, A, B, C,  9, 12, 0x8B44F7AF );
+    P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
+    P( B, C, D, A, 11, 22, 0x895CD7BE );
+    P( A, B, C, D, 12,  7, 0x6B901122 );
+    P( D, A, B, C, 13, 12, 0xFD987193 );
+    P( C, D, A, B, 14, 17, 0xA679438E );
+    P( B, C, D, A, 15, 22, 0x49B40821 );
+
+#undef F
+
+#define F(x,y,z) (y ^ (z & (x ^ y)))
+
+    P( A, B, C, D,  1,  5, 0xF61E2562 );
+    P( D, A, B, C,  6,  9, 0xC040B340 );
+    P( C, D, A, B, 11, 14, 0x265E5A51 );
+    P( B, C, D, A,  0, 20, 0xE9B6C7AA );
+    P( A, B, C, D,  5,  5, 0xD62F105D );
+    P( D, A, B, C, 10,  9, 0x02441453 );
+    P( C, D, A, B, 15, 14, 0xD8A1E681 );
+    P( B, C, D, A,  4, 20, 0xE7D3FBC8 );
+    P( A, B, C, D,  9,  5, 0x21E1CDE6 );
+    P( D, A, B, C, 14,  9, 0xC33707D6 );
+    P( C, D, A, B,  3, 14, 0xF4D50D87 );
+    P( B, C, D, A,  8, 20, 0x455A14ED );
+    P( A, B, C, D, 13,  5, 0xA9E3E905 );
+    P( D, A, B, C,  2,  9, 0xFCEFA3F8 );
+    P( C, D, A, B,  7, 14, 0x676F02D9 );
+    P( B, C, D, A, 12, 20, 0x8D2A4C8A );
+
+#undef F
+    
+#define F(x,y,z) (x ^ y ^ z)
+
+    P( A, B, C, D,  5,  4, 0xFFFA3942 );
+    P( D, A, B, C,  8, 11, 0x8771F681 );
+    P( C, D, A, B, 11, 16, 0x6D9D6122 );
+    P( B, C, D, A, 14, 23, 0xFDE5380C );
+    P( A, B, C, D,  1,  4, 0xA4BEEA44 );
+    P( D, A, B, C,  4, 11, 0x4BDECFA9 );
+    P( C, D, A, B,  7, 16, 0xF6BB4B60 );
+    P( B, C, D, A, 10, 23, 0xBEBFBC70 );
+    P( A, B, C, D, 13,  4, 0x289B7EC6 );
+    P( D, A, B, C,  0, 11, 0xEAA127FA );
+    P( C, D, A, B,  3, 16, 0xD4EF3085 );
+    P( B, C, D, A,  6, 23, 0x04881D05 );
+    P( A, B, C, D,  9,  4, 0xD9D4D039 );
+    P( D, A, B, C, 12, 11, 0xE6DB99E5 );
+    P( C, D, A, B, 15, 16, 0x1FA27CF8 );
+    P( B, C, D, A,  2, 23, 0xC4AC5665 );
+
+#undef F
+
+#define F(x,y,z) (y ^ (x | ~z))
+
+    P( A, B, C, D,  0,  6, 0xF4292244 );
+    P( D, A, B, C,  7, 10, 0x432AFF97 );
+    P( C, D, A, B, 14, 15, 0xAB9423A7 );
+    P( B, C, D, A,  5, 21, 0xFC93A039 );
+    P( A, B, C, D, 12,  6, 0x655B59C3 );
+    P( D, A, B, C,  3, 10, 0x8F0CCC92 );
+    P( C, D, A, B, 10, 15, 0xFFEFF47D );
+    P( B, C, D, A,  1, 21, 0x85845DD1 );
+    P( A, B, C, D,  8,  6, 0x6FA87E4F );
+    P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
+    P( C, D, A, B,  6, 15, 0xA3014314 );
+    P( B, C, D, A, 13, 21, 0x4E0811A1 );
+    P( A, B, C, D,  4,  6, 0xF7537E82 );
+    P( D, A, B, C, 11, 10, 0xBD3AF235 );
+    P( C, D, A, B,  2, 15, 0x2AD7D2BB );
+    P( B, C, D, A,  9, 21, 0xEB86D391 );
+
+#undef F
+
+    ctx->state[0] += A;
+    ctx->state[1] += B;
+    ctx->state[2] += C;
+    ctx->state[3] += D;
+}
+
+void md5_update( md5_context *ctx, uint8 *input, uint32 length )
+{
+    uint32 left, fill;
+
+    if( ! length ) return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = 64 - left;
+
+    ctx->total[0] += length;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if( ctx->total[0] < length )
+        ctx->total[1]++;
+
+    if( left && length >= fill )
+    {
+        memcpy( (void *) (ctx->buffer + left),
+                (void *) input, fill );
+        md5_process( ctx, ctx->buffer );
+        length -= fill;
+        input  += fill;
+        left = 0;
+    }
+
+    while( length >= 64 )
+    {
+        md5_process( ctx, input );
+        length -= 64;
+        input  += 64;
+    }
+
+    if( length )
+    {
+        memcpy( (void *) (ctx->buffer + left),
+                (void *) input, length );
+    }
+}
+
+static uint8 md5_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+void md5_finish( md5_context *ctx, uint8 digest[16] )
+{
+    uint32 last, padn;
+    uint32 high, low;
+    uint8 msglen[8];
+
+    high = ( ctx->total[0] >> 29 )
+         | ( ctx->total[1] <<  3 );
+    low  = ( ctx->total[0] <<  3 );
+
+    PUT_UINT32( low,  msglen, 0 );
+    PUT_UINT32( high, msglen, 4 );
+
+    last = ctx->total[0] & 0x3F;
+    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+    md5_update( ctx, md5_padding, padn );
+    md5_update( ctx, msglen, 8 );
+
+    PUT_UINT32( ctx->state[0], digest,  0 );
+    PUT_UINT32( ctx->state[1], digest,  4 );
+    PUT_UINT32( ctx->state[2], digest,  8 );
+    PUT_UINT32( ctx->state[3], digest, 12 );
+}
+
+#define TEST
+#ifdef TEST
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/*
+ * those are the standard RFC 1321 test vectors
+ */
+
+static char *msg[] = 
+{
+    "",
+    "a",
+    "abc",
+    "message digest",
+    "abcdefghijklmnopqrstuvwxyz",
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+    "12345678901234567890123456789012345678901234567890123456789012" \
+        "345678901234567890"
+};
+
+static char *val[] =
+{
+    "d41d8cd98f00b204e9800998ecf8427e",
+    "0cc175b9c0f1b6a831c399e269772661",
+    "900150983cd24fb0d6963f7d28e17f72",
+    "f96b697d7cb7938d525a2f31aaf161d0",
+    "c3fcd3d76192e4007dfb496cca67e13b",
+    "d174ab98d277d9f5a5611c2c9f419d9f",
+    "57edf4a22be3c955ac49da2e2107b67a"
+};
+
+char* md5(char* pass, char* output)
+{
+    md5_context ctx;
+    int j;
+    unsigned char md5sum[16];
+
+    md5_starts( &ctx );
+    md5_update( &ctx, (uint8 *) pass, strlen(pass));
+    md5_finish( &ctx, md5sum );
+    for(j = 0; j<16; j++)
+    {
+        sprintf(output + j * 2, "%02x", md5sum[j]);
+    }
+    printf("The hash of %s is %s\n\n", pass, output);
+}
+
 const char *
 cryptpass(const char *pass, char *buffer)
 {
-    int seed;
-    do { seed = rand(); } while (!seed);
-    return cryptpass_real(pass, buffer, seed);
+    return md5(pass, buffer);
 }
 
 int
@@ -364,10 +667,14 @@ checkpass(const char *pass, const char *crypt)
         strncpy(hseed, crypt+1, 8);
         hseed[8] = 0;
         seed = strtoul(hseed, NULL, 16);
+        cryptpass_real(pass, new_crypt, seed);
     } else {
-        /* old-style crypt, use "seed" of 0 */
-        seed = 0;
+        /* new "old-style" md5 crypt compatable with php, md5sum etc */
+        md5(pass, new_crypt);
     }
-    cryptpass_real(pass, new_crypt, seed);
     return !strcmp(crypt, new_crypt);
 }
+
+
+
+#endif
index 4febb69f5ec0f886abe7571234d4e8385a2136da..7286f50d471f174e0a1182503d938f55efd89b53 100644 (file)
--- a/src/md5.h
+++ b/src/md5.h
@@ -1,3 +1,35 @@
+#ifndef _MD5_H
+#define _MD5_H
+
+#ifndef uint8
+#define uint8  unsigned char
+#endif
+
+#ifndef uint32
+#define uint32 unsigned long int
+#endif
+
+typedef struct
+{
+    uint32 total[2];
+    uint32 state[4];
+    uint8 buffer[64];
+}
+md5_context;
+
+void md5_starts( md5_context *ctx );
+void md5_update( md5_context *ctx, uint8 *input, uint32 length );
+void md5_finish( md5_context *ctx, uint8 digest[16] );
+
+#endif /* md5.h */
+
+
+/* ---------------------------------------
+ *           OLD CRAP HERE 
+ *           DELETE THIS SOME DAY
+ *
+ *----------------------------------------*/
+
 /* GLOBAL.H - RSAREF types and constants */
 
 /* PROTOTYPES should be set to one if and only if the compiler supports
index 593e112b0f4ec7a34f00d6753d7e9778819bfef0..2127aeadddbc004a3d64a6f6636ba68f6fc849c9 100644 (file)
@@ -290,9 +290,39 @@ static const struct message_entry msgtab[] = {
     { "NSMSG_SET_TITLE", "$bTITLE:        $b%s" },
     { "NSMSG_SET_FAKEHOST", "$bFAKEHOST:    $b%s" },
     { "NSEMAIL_ACTIVATION_SUBJECT", "Account verification for %s" },
-    { "NSEMAIL_ACTIVATION_BODY", "This email has been sent to verify that this email address belongs to the person who tried to register an account on %1$s.  Your cookie is:\n    %2$s\nTo verify your email address and complete the account registration, log on to %1$s and type the following command:\n    /msg %3$s@%4$s COOKIE %5$s %2$s\nThis command is only used once to complete your account registration, and never again. Once you have run this command, you will need to authenticate everytime you reconnect to the network. To do this, you will have to type this command every time you reconnect:\n    /msg %3$s@%4$s AUTH %5$s your-password\n Please remember to fill in 'your-password' with the actual password you gave to us when you registered.\n\nIf you did NOT request this account, you do not need to do anything.  Please contact the %1$s staff if you have questions, and be sure to check our website." },
+    { "NSEMAIL_ACTIVATION_BODY", 
+        "This email has been sent to verify that this email address belongs to the person who tried to register an account on %1$s.  Your cookie is:\n"
+        "%2$s\n"
+        "To verify your email address and complete the account registration, log on to %1$s and type the following command:\n"
+        "/msg %3$s@%4$s COOKIE %5$s %2$s\n"
+        "This command is only used once to complete your account registration, and never again. Once you have run this command, you will need to authenticate everytime you reconnect to the network. To do this, you will have to type this command every time you reconnect:\n"
+        "/msg %3$s@%4$s AUTH %5$s your-password\n"
+        "(Please remember to fill in 'your-password' with the actual password you gave to us when you registered.)\n"
+        "OR configure Login-On-Connect (see http://www.afternet.org/login-on-connect for instructions) to connect pre-logged in every time.\n"
+        "\n"
+        "If you did NOT request this account, you do not need to do anything.\n"
+        "Please contact the %1$s staff if you have questions, and be sure to check our website." },
+    { "NSEMAIL_ACTIVATION_BODY_WEB", 
+        "This email has been sent to verify that this email address belongs to the person who tried to register an account on %1$s.  Your cookie is:\n"
+        "%2$s\n"
+        "To verify your email address and complete the account registration, visit the following URL:\n"
+        "http://www.afternet.org/play/index.php?option=com_registration&task=activate&username=%5$s&cookie=%2$s\n"
+        "\n"
+        "If you did NOT request this account, you do not need to do anything.\n"
+        "Please contact the %1$s staff if you have questions, and be sure to check our website." },
     { "NSEMAIL_PASSWORD_CHANGE_SUBJECT", "Password change verification on %s" },
-    { "NSEMAIL_PASSWORD_CHANGE_BODY", "This email has been sent to verify that you wish to change the password on your account %5$s.  Your cookie is %2$s.\nTo complete the password change, log on to %1$s and type the following command:\n    /msg %3$s@%4$s COOKIE %5$s %2$s\nIf you did NOT request your password to be changed, you do not need to do anything.  Please contact the %1$s staff if you have questions." },
+    { "NSEMAIL_PASSWORD_CHANGE_BODY", 
+        "This email has been sent to verify that you wish to change the password on your account %5$s.  Your cookie is %2$s.\n"
+        "To complete the password change, log on to %1$s and type the following command:\n"
+        "/msg %3$s@%4$s COOKIE %5$s %2$s\n"
+        "If you did NOT request your password to be changed, you do not need to do anything.\n"
+        "Please contact the %1$s staff if you have questions." },
+    { "NSEMAIL_PASSWORD_CHANGE_BODY_WEB", 
+        "This email has been sent to verify that you wish to change the password on your account %5$s.  Your cookie is %2$s.\n"
+        "To complete the password change, click the following URL:\n"
+        "http://www.afternet.org/play/index.php?option=com_registration&task=passcookie&username=%5$s&cookie=%2$s\n"
+        "If you did NOT request your password to be changed, you do not need to do anything.\n"
+        "Please contact the %1$s staff if you have questions." },
     { "NSEMAIL_EMAIL_CHANGE_SUBJECT", "Email address change verification for %s" },
     { "NSEMAIL_EMAIL_CHANGE_BODY_NEW", "This email has been sent to verify that your email address belongs to the same person as account %5$s on %1$s.  The SECOND HALF of your cookie is %2$.*6$s.\nTo verify your address as associated with this account, log on to %1$s and type the following command:\n    /msg %3$s@%4$s COOKIE %5$s ?????%2$.*6$s\n(Replace the ????? with the FIRST HALF of the cookie, as sent to your OLD email address.)\nIf you did NOT request this email address to be associated with this account, you do not need to do anything.  Please contact the %1$s staff if you have questions." },
     { "NSEMAIL_EMAIL_CHANGE_BODY_OLD", "This email has been sent to verify that you want to change your email for account %5$s on %1$s from this address to %7$s.  The FIRST HALF of your cookie is %2$.*6$s\nTo verify your new address as associated with this account, log on to %1$s and type the following command:\n    /msg %3$s@%4$s COOKIE %5$s %2$.*6$s?????\n(Replace the ????? with the SECOND HALF of the cookie, as sent to your NEW email address.)\nIf you did NOT request this change of email address, you do not need to do anything.  Please contact the %1$s staff if you have questions." },
@@ -997,7 +1027,7 @@ nickserv_bake_cookie(struct handle_cookie *cookie)
 }
 
 static void
-nickserv_make_cookie(struct userNode *user, struct handle_info *hi, enum cookie_type type, const char *cookie_data)
+nickserv_make_cookie(struct userNode *user, struct handle_info *hi, enum cookie_type type, const char *cookie_data, int weblink)
 {
     struct handle_cookie *cookie;
     char subject[128], body[4096], *misc;
@@ -1026,7 +1056,12 @@ nickserv_make_cookie(struct userNode *user, struct handle_info *hi, enum cookie_
         send_message(user, nickserv, "NSMSG_USE_COOKIE_REGISTER");
         fmt = handle_find_message(hi, "NSEMAIL_ACTIVATION_SUBJECT");
         snprintf(subject, sizeof(subject), fmt, netname);
-        fmt = handle_find_message(hi, "NSEMAIL_ACTIVATION_BODY");
+
+        if(weblink)
+            fmt = handle_find_message(hi, "NSEMAIL_ACTIVATION_BODY_WEB");
+        else
+            fmt = handle_find_message(hi, "NSEMAIL_ACTIVATION_BODY");
+
         snprintf(body, sizeof(body), fmt, netname, cookie->cookie, nickserv->nick, self->name, hi->handle);
         first_time = 1;
         break;
@@ -1034,7 +1069,10 @@ nickserv_make_cookie(struct userNode *user, struct handle_info *hi, enum cookie_
         send_message(user, nickserv, "NSMSG_USE_COOKIE_RESETPASS");
         fmt = handle_find_message(hi, "NSEMAIL_PASSWORD_CHANGE_SUBJECT");
         snprintf(subject, sizeof(subject), fmt, netname);
-        fmt = handle_find_message(hi, "NSEMAIL_PASSWORD_CHANGE_BODY");
+        if(weblink)
+            fmt = handle_find_message(hi, "NSEMAIL_PASSWORD_CHANGE_BODY_WEB");
+        else
+            fmt = handle_find_message(hi, "NSEMAIL_PASSWORD_CHANGE_BODY");
         snprintf(body, sizeof(body), fmt, netname, cookie->cookie, nickserv->nick, self->name, hi->handle);
         break;
     case EMAIL_CHANGE:
@@ -1118,7 +1156,7 @@ static NICKSERV_FUNC(cmd_register)
 {
     struct handle_info *hi;
     const char *email_addr, *password;
-    int no_auth;
+    int no_auth, weblink;
 
     if (!IsOper(user) && !dict_size(nickserv_handle_dict)) {
        /* Require the first handle registered to belong to someone +o. */
@@ -1151,6 +1189,7 @@ static NICKSERV_FUNC(cmd_register)
         return 0;
     }
 
+
     if ((argc >= 4) && nickserv_conf.email_enabled) {
         struct handle_info_list *hil;
         const char *str;
@@ -1193,6 +1232,13 @@ static NICKSERV_FUNC(cmd_register)
 
     password = argv[2];
     argv[2] = "****";
+    /* Webregister hack - send URL instead of IRC cookie 
+     * commands in email
+     */
+    if((argc >= 5) && !strcmp(argv[4],"WEBLINK"))
+        weblink = 1;
+    else
+        weblink = 0;
     if (!(hi = nickserv_register(user, user, argv[1], password, no_auth)))
         return 0;
     /* Add any masks they should get. */
@@ -1216,7 +1262,7 @@ static NICKSERV_FUNC(cmd_register)
 
     /* If they need to do email verification, tell them. */
     if (no_auth)
-        nickserv_make_cookie(user, hi, ACTIVATION, hi->passwd);
+        nickserv_make_cookie(user, hi, ACTIVATION, hi->passwd, weblink);
 
     /* Set registering flag.. */
     user->modes |= FLAGS_REGISTERING; 
@@ -1788,7 +1834,7 @@ static NICKSERV_FUNC(cmd_authcookie)
         reply("MSG_SET_EMAIL_ADDR");
         return 0;
     }
-    nickserv_make_cookie(user, hi, ALLOWAUTH, NULL);
+    nickserv_make_cookie(user, hi, ALLOWAUTH, NULL, 0);
     return 1;
 }
 
@@ -1818,8 +1864,13 @@ static NICKSERV_FUNC(cmd_resetpass)
 {
     struct handle_info *hi;
     char crypted[MD5_CRYPT_LENGTH];
+    int weblink;
 
     NICKSERV_MIN_PARMS(3);
+    if(argc >= 4 && !strcmp(argv[3], "WEBLINK"))
+        weblink = 1;
+    else
+        weblink = 0;
     if (user->handle_info) {
         reply("NSMSG_ALREADY_AUTHED", user->handle_info->handle);
         return 0;
@@ -1841,7 +1892,7 @@ static NICKSERV_FUNC(cmd_resetpass)
     }
     cryptpass(argv[2], crypted);
     argv[2] = "****";
-    nickserv_make_cookie(user, hi, PASSWORD_CHANGE, crypted);
+    nickserv_make_cookie(user, hi, PASSWORD_CHANGE, crypted, weblink);
     return 1;
 }
 
@@ -2378,7 +2429,7 @@ static OPTION_FUNC(opt_email)
         if (hi->email_addr && !irccasecmp(hi->email_addr, argv[1]))
             send_message(user, nickserv, "NSMSG_EMAIL_SAME");
         else if (!override)
-                nickserv_make_cookie(user, hi, EMAIL_CHANGE, argv[1]);
+                nickserv_make_cookie(user, hi, EMAIL_CHANGE, argv[1], 0);
         else {
             nickserv_set_email_addr(hi, argv[1]);
             if (hi->cookie)