"Fossies" - the Fresh Open Source Software Archive

Member "mod_ntlm2-0.1/ntlmssp.inc.c" (23 Feb 2003, 12562 Bytes) of package /linux/www/apache_httpd_modules/old/mod_ntlm2-0.1.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  * $Id: ntlmssp.inc.c,v 1.2.4.1 2003/02/23 15:56:26 casz Exp $
    3  *
    4  */
    5 
    6 #define MAX_HOSTLEN 32
    7 #define MAX_DOMLEN 32
    8 #define MAX_USERLEN 32
    9 #define RESP_LEN 24
   10 #define NONCE_LEN 8
   11 
   12 /* fhz, 01-10-15 : borrowed from samba code */
   13 /* NTLMSSP negotiation flags */
   14 #define NTLMSSP_NEGOTIATE_UNICODE          0x00000001
   15 #define NTLMSSP_NEGOTIATE_OEM              0x00000002
   16 #define NTLMSSP_REQUEST_TARGET             0x00000004
   17 #define NTLMSSP_NEGOTIATE_SIGN             0x00000010
   18 #define NTLMSSP_NEGOTIATE_SEAL             0x00000020
   19 #define NTLMSSP_NEGOTIATE_LM_KEY           0x00000080
   20 #define NTLMSSP_NEGOTIATE_NTLM             0x00000200
   21 #define NTLMSSP_NEGOTIATE_00001000         0x00001000
   22 #define NTLMSSP_NEGOTIATE_00002000         0x00002000
   23 #define NTLMSSP_NEGOTIATE_ALWAYS_SIGN      0x00008000
   24 #define NTLMSSP_TARGET_TYPE_DOMAIN     0x00010000
   25 #define NTLMSSP_TARGET_TYPE_SERVER     0x00020000
   26 #define NTLMSSP_NEGOTIATE_NTLM2            0x00080000
   27 #define NTLMSSP_NEGOTIATE_TARGET_INFO      0x00800000
   28 #define NTLMSSP_NEGOTIATE_128              0x20000000
   29 #define NTLMSSP_NEGOTIATE_KEY_EXCH         0x40000000
   30 
   31 #define SMBD_NTLMSSP_NEG_FLAGS 0x000082b1
   32 #define NTLM_NTLMSSP_NEG_FLAGS 0x00008206
   33 /* 8201 8207 */
   34 
   35 #define LEN_NTLMSSP_FLAGS 4
   36 #define OFFSET_MSG1_NTLMSSP_FLAGS 12
   37 
   38 struct ntlm_msg1 {
   39     unsigned char protocol[8];
   40     unsigned char type;         /* 1 */
   41     unsigned char zero1[3];
   42     unsigned char flags[2];
   43     unsigned char zero2[2];
   44 
   45     unsigned char dom_len[4];
   46     unsigned char dom_off[4];
   47 
   48     unsigned char host_len[4];
   49     unsigned char host_off[4];
   50 
   51 #if 0
   52     unsigned char data[0];
   53 #endif
   54 } __attribute__((packed));
   55 
   56 struct ntlm_msg2 {
   57     unsigned char protocol[8];
   58     unsigned char type;         /* 2 */
   59     unsigned char zero1[7];
   60     unsigned char msg_len[4];
   61     unsigned char flags[2];
   62     unsigned char zero2[2];
   63 
   64     unsigned char nonce[8];
   65     unsigned char zero3[8];
   66 } __attribute__((packed));
   67 
   68 struct ntlm_msg3 {
   69     unsigned char protocol[8];
   70     unsigned char type;         /* 3 */
   71     unsigned char zero1[3];
   72 
   73     unsigned char lm_len[4];
   74     unsigned char lm_off[4];
   75 
   76     unsigned char nt_len[4];
   77     unsigned char nt_off[4];
   78 
   79     unsigned char dom_len[4];
   80     unsigned char dom_off[4];
   81 
   82     unsigned char user_len[4];
   83     unsigned char user_off[4];
   84 
   85     unsigned char host_len[4];
   86     unsigned char host_off[4];
   87 
   88     unsigned char msg_len[4]; /* Win9x: data begins here! */
   89 
   90 #if 0
   91     unsigned char data[0];
   92 #endif
   93 } __attribute__((packed));
   94 
   95 struct ntlm_msg2_win9x {
   96     unsigned char protocol[8];
   97     unsigned char type;         /* 2 */
   98     unsigned char zero1[3];
   99     unsigned char dom_len1[2];
  100     unsigned char dom_len2[2];
  101     unsigned char dom_off[4];
  102     unsigned char flags[2];
  103     unsigned char zero2[2];
  104 
  105     unsigned char nonce[8];
  106     unsigned char zero3[8];
  107     unsigned char zero4[4];
  108     unsigned char msg_len[4];
  109     unsigned char dom[MAX_DOMLEN];
  110 } __attribute__((packed));
  111 
  112 /* size without dom[] : */
  113 #define NTLM_MSG2_WIN9X_FIXED_SIZE (sizeof(struct ntlm_msg2_win9x)-MAX_DOMLEN)
  114 
  115 
  116 typedef struct ntlmssp_info {
  117     int msg_type;
  118     unsigned char user[MAX_USERLEN + 1];
  119     unsigned char host[MAX_HOSTLEN + 1];
  120     unsigned char domain[MAX_DOMLEN + 1];
  121     unsigned char lm[RESP_LEN];
  122     unsigned char nt[RESP_LEN];
  123 } ntlmssp_info_rec;
  124 
  125 #define little_endian_word(x) x[0] + (((unsigned)x[1]) << 8)
  126 /* fhz 02-02-09: typecasting is needed for a generic use */
  127 #define set_little_endian_word(x,y) (*((char *)x))=(y&0xff);*(((char*)x)+1)=((y>>8)&0xff)
  128 
  129 static int 
  130 ntlm_msg_type(unsigned char *raw_msg, unsigned msglen)
  131 {
  132     struct ntlm_msg1 *msg = (struct ntlm_msg1 *) raw_msg;
  133 
  134     if (msglen < 9)
  135         return -1;
  136     if (strncmp(msg->protocol, "NTLMSSP", 8))
  137         return -1;
  138     return msg->type;
  139 }
  140 
  141 static int 
  142 ntlm_extract_mem(request_rec * r, unsigned char *dst,
  143                  unsigned char *src, unsigned srclen,
  144                  unsigned char *off, unsigned char *len,
  145                  unsigned max)
  146 {
  147     unsigned o = little_endian_word(off);
  148     unsigned l = little_endian_word(len);
  149     if (l > max)
  150         return -1;
  151     if (o >= srclen)
  152         return -1;
  153     if (o + l > srclen)
  154         return -1;
  155     src += o;
  156     while (l-- > 0)
  157         *dst++ = *src++;
  158     return 0;
  159 }
  160 
  161 static int 
  162 ntlm_extract_string(request_rec * r, unsigned char *dst,
  163                     unsigned char *src, unsigned srclen,
  164                     unsigned char *off, unsigned char *len,
  165                     unsigned max)
  166 {
  167     unsigned o = little_endian_word(off);
  168     unsigned l = little_endian_word(len);
  169     if (l > max)
  170         return -1;
  171     if (o >= srclen)
  172         return -1;
  173     if (o + l > srclen)
  174         return -1;
  175     src += o;
  176     while (l-- > 0) {
  177         /* +csz 2003/02/20 - En algunos casos vienen \0 entremedio */
  178         if ( *src != '\0' ) {
  179             *dst = *src;
  180             dst++;
  181         }
  182         src++;
  183     }
  184     *dst = 0;
  185     return 0;
  186 }
  187 
  188 static int
  189 ntlm_put_in_unicode(unsigned char *dst,
  190                      unsigned char *src, unsigned srclen, unsigned max)
  191 {
  192     unsigned l = srclen*2;
  193     if (l > max)
  194         l=max; /* fhz: bad very bad */
  195     while (l > 0) {
  196         /*  ASCII to unicode*/
  197         *dst++ = *src++;
  198     *dst++=0;
  199     l -=2;
  200     }
  201     return 0;
  202 
  203 
  204 
  205 }
  206 
  207 static int 
  208 ntlm_extract_unicode(request_rec * r, unsigned char *dst,
  209                      unsigned char *src, unsigned srclen,
  210                      unsigned char *off, unsigned char *len,
  211                      unsigned max)
  212 {
  213     unsigned o = little_endian_word(off);
  214     unsigned l = little_endian_word(len) / 2;   /* Unicode! */
  215     if (l > max)
  216         return -1;
  217     if (o >= srclen)
  218         return -1;
  219     if (o + l > srclen)
  220         return -1;
  221     src += o;
  222     while (l > 0) {
  223         /* Unicode to ASCII */
  224         *dst++ = *src;
  225         src += 2;
  226         l -= 2;
  227     }
  228     *dst = 0;
  229     return 0;
  230 }
  231 
  232 static int 
  233 ntlm_msg1_getntlmssp_flags(request_rec * r, unsigned char *raw_msg,
  234                       unsigned char *ntlmssp_flags)
  235 {
  236     struct ntlm_msg1 *msg = (struct ntlm_msg1 *) raw_msg;
  237     *ntlmssp_flags=little_endian_word(msg->flags);
  238     return 0;
  239 }
  240 
  241 static int 
  242 ntlm_msg1_gethostname(request_rec * r, unsigned char *raw_msg,
  243                       unsigned msglen, unsigned char *hostname)
  244 {
  245     struct ntlm_msg1 *msg = (struct ntlm_msg1 *) raw_msg;
  246     if (ntlm_extract_string(r, hostname, (char *) msg, msglen,
  247                             msg->host_off, msg->host_len, MAX_HOSTLEN))
  248         return 1;
  249     return 0;
  250 }
  251 
  252 static int 
  253 ntlm_msg1_getdomainname(request_rec * r, unsigned char *raw_msg,
  254                         unsigned msglen, unsigned char *domainname)
  255 {
  256     struct ntlm_msg1 *msg = (struct ntlm_msg1 *) raw_msg;
  257     if (ntlm_extract_string(r, domainname, (char *) msg,
  258                             msglen, msg->dom_off, msg->dom_len, MAX_DOMLEN))
  259         return 2;
  260     return 0;
  261 }
  262 
  263 static int 
  264 ntlm_msg3_getlm(request_rec * r, unsigned char *raw_msg, unsigned msglen,
  265                 unsigned char *lm)
  266 {
  267     struct ntlm_msg3 *msg = (struct ntlm_msg3 *) raw_msg;
  268     if (ntlm_extract_mem(r, lm, (char *) msg, msglen, msg->lm_off,
  269                          msg->lm_len, RESP_LEN))
  270         return 4;
  271     return 0;
  272 }
  273 
  274 static int 
  275 ntlm_msg3_getnt(request_rec * r, unsigned char *raw_msg, unsigned msglen,
  276                 unsigned char *nt)
  277 {
  278     struct ntlm_msg3 *msg = (struct ntlm_msg3 *) raw_msg;
  279     if (ntlm_extract_mem(r, nt, (char *) msg, msglen, msg->nt_off,
  280                          msg->nt_len, RESP_LEN)) 
  281     /* Win9x: we can't extract nt ... so we use lm... */
  282         if (ntlm_extract_mem(r, nt, (char *) msg, msglen, msg->lm_off,
  283                          msg->lm_len, RESP_LEN)) 
  284         return 8;
  285     return 0;
  286 }
  287 
  288 static int 
  289 ntlm_msg3_getusername(request_rec * r, unsigned char *raw_msg,
  290                       unsigned msglen, unsigned char *username,
  291               unsigned ntlmssp_flags)
  292 {
  293     struct ntlm_msg3 *msg = (struct ntlm_msg3 *) raw_msg;
  294     int c;
  295     if (ntlmssp_flags & NTLMSSP_NEGOTIATE_UNICODE) {
  296         if (ntlm_extract_unicode(r, username, (char *) msg, msglen,
  297                              msg->user_off, msg->user_len, MAX_USERLEN))
  298         return 16;
  299     }
  300     else { /* ascii */
  301         if (ntlm_extract_string(r, username, (char *) msg, msglen,
  302                              msg->user_off, msg->user_len, MAX_USERLEN))
  303         return 16;
  304         else {
  305         /* Win9x client leave username in uppercase...fix it: */
  306         while (*username!=(unsigned char)NULL) {
  307             c=tolower((int)*username);
  308             *username=(unsigned char)c;
  309             username++;
  310         }
  311         }
  312     }
  313     return 0;
  314 }
  315 
  316 static int 
  317 ntlm_msg3_gethostname(request_rec * r, unsigned char *raw_msg, unsigned msglen,
  318                       unsigned char *hostname,unsigned ntlmssp_flags)
  319 {
  320     struct ntlm_msg3 *msg = (struct ntlm_msg3 *) raw_msg;
  321     if (ntlmssp_flags & NTLMSSP_NEGOTIATE_UNICODE) {
  322         if (ntlm_extract_unicode(r, hostname, (char *) msg, msglen,
  323                              msg->host_off, msg->host_len, MAX_HOSTLEN))
  324         return 0;  /* this one FAILS, but since the value is not used,
  325                 * we just pretend it was ok. */
  326     }
  327     else { /* ascii */
  328         if (ntlm_extract_string(r, hostname, (char *) msg, msglen,
  329                              msg->host_off, msg->host_len, MAX_HOSTLEN))
  330         return 0;  /* this one FAILS, but since the value is not used,
  331                 * we just pretend it was ok. */
  332     }
  333     return 0;
  334 }
  335 
  336 static int 
  337 ntlm_msg3_getdomainname(request_rec * r, unsigned char *raw_msg,
  338                         unsigned msglen, unsigned char *domainname,
  339             unsigned ntlmssp_flags)
  340 {
  341     struct ntlm_msg3 *msg = (struct ntlm_msg3 *) raw_msg;
  342     if (ntlmssp_flags & NTLMSSP_NEGOTIATE_UNICODE) {
  343         if (ntlm_extract_unicode(r, domainname, (char *) msg, msglen,
  344                              msg->dom_off, msg->dom_len, MAX_DOMLEN))
  345         return 64;
  346     }
  347     else { /* asii */
  348         if (ntlm_extract_string(r, domainname, (char *) msg, msglen,
  349                              msg->dom_off, msg->dom_len, MAX_DOMLEN))
  350         return 64;
  351     }
  352     return 0;
  353 }
  354 
  355 static int 
  356 ntlm_decode_msg(request_rec * r, struct ntlmssp_info *info,
  357                 unsigned char *raw_msg, unsigned msglen,
  358         unsigned *ntlmssp_flags)
  359 {
  360     switch (info->msg_type = ntlm_msg_type(raw_msg, msglen)) {
  361       case 1:
  362           return ntlm_msg1_getntlmssp_flags(r,raw_msg,(unsigned char*)ntlmssp_flags)
  363          + ntlm_msg1_gethostname(r, raw_msg, msglen, info->host)
  364               + ntlm_msg1_getdomainname(r, raw_msg, msglen, info->domain);
  365       case 3:
  366           return ntlm_msg3_getlm(r, raw_msg, msglen, info->lm)
  367               + ntlm_msg3_getnt(r, raw_msg, msglen, info->nt)
  368               + ntlm_msg3_getusername(r, raw_msg, msglen, info->user,*ntlmssp_flags)
  369               + ntlm_msg3_gethostname(r, raw_msg, msglen, info->host,*ntlmssp_flags)
  370               + ntlm_msg3_getdomainname(r, raw_msg, msglen, info->domain,*ntlmssp_flags);
  371     }
  372     return -1;
  373 }
  374 
  375 static int 
  376 ntlm_encode_msg2(unsigned char *nonce, struct ntlm_msg2 *msg)
  377 {
  378     memset(msg, 0, sizeof(struct ntlm_msg2));
  379     strcpy(msg->protocol, "NTLMSSP");
  380     msg->type = 0x02;
  381     set_little_endian_word(msg->msg_len, sizeof(struct ntlm_msg2));
  382     set_little_endian_word(msg->flags, 0x8201);
  383     memcpy(msg->nonce, nonce, sizeof(msg->nonce));
  384     return 0;
  385 }
  386 
  387 static int 
  388 ntlm_encode_msg2_win9x(unsigned char *nonce, struct ntlm_msg2_win9x *msg,char *domainname,unsigned ntlmssp_flags)
  389 {
  390     unsigned int size,len,flags;
  391 
  392     memset(msg, 0, sizeof(struct ntlm_msg2_win9x));
  393     strcpy(msg->protocol, "NTLMSSP");
  394     msg->type = 0x02;
  395     if (ntlmssp_flags & NTLMSSP_NEGOTIATE_UNICODE) {
  396        /* unicode case */
  397 
  398         len=strlen(domainname);
  399         ntlm_put_in_unicode((char *)msg->dom,domainname, 
  400         len, MAX_DOMLEN);
  401         len=len*2;
  402         if (len>MAX_DOMLEN)
  403             len=MAX_DOMLEN; /* fhz: bad very bad */
  404         flags=NTLM_NTLMSSP_NEG_FLAGS | NTLMSSP_NEGOTIATE_UNICODE;
  405     } else {
  406         /* ascii case */
  407         len=strlen(domainname);
  408         if (len>MAX_DOMLEN)
  409             len=MAX_DOMLEN; /* fhz: bad very bad */
  410         strncpy(msg->dom,domainname,len); 
  411         flags=NTLM_NTLMSSP_NEG_FLAGS;
  412     }
  413     size=NTLM_MSG2_WIN9X_FIXED_SIZE+len;
  414     set_little_endian_word(msg->dom_off, NTLM_MSG2_WIN9X_FIXED_SIZE);
  415     set_little_endian_word(msg->dom_len1,len);
  416     set_little_endian_word(msg->dom_len2,len);
  417     set_little_endian_word(msg->msg_len,size);
  418     set_little_endian_word(msg->flags,flags); 
  419     if (ntlmssp_flags & NTLMSSP_REQUEST_TARGET) 
  420          set_little_endian_word(msg->zero2, 0x01);  /* == set NTLMSSP_TARGET_TYPE_DOMAIN */
  421         
  422     memcpy(msg->nonce, nonce, sizeof(msg->nonce));
  423     return size;
  424 }