login.c
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:34k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: login.c,v $
  4.  * PRODUCTION Revision 1000.0  2003/10/29 20:34:56  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [ORIGINAL] Dev-tree R1.3
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
  10.  * Copyright (C) 1998-1999  Brian Bruns
  11.  *
  12.  * This library is free software; you can redistribute it and/or
  13.  * modify it under the terms of the GNU Library General Public
  14.  * License as published by the Free Software Foundation; either
  15.  * version 2 of the License, or (at your option) any later version.
  16.  *
  17.  * This library is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  20.  * Library General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU Library General Public
  23.  * License along with this library; if not, write to the
  24.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  25.  * Boston, MA 02111-1307, USA.
  26.  */
  27. #include <tds_config.h>
  28. #include "tds.h"
  29. #include "tdsutil.h"
  30. #ifdef DMALLOC
  31. #include <dmalloc.h>
  32. #endif
  33. #ifdef WIN32                                           
  34. #define IOCTL(a,b,c) ioctlsocket(a, b, c)
  35. #else
  36. #define IOCTL(a,b,c) ioctl(a, b, c)
  37. #endif
  38. #ifdef HAVE_SSL
  39. #define DOMAIN 1
  40. #else
  41. #define DOMAIN 0
  42. #endif
  43. static char  software_version[]   = "$Id: login.c,v 1000.0 2003/10/29 20:34:56 gouriano Exp $";
  44. static void *no_unused_var_warn[] = {software_version,
  45.                                      no_unused_var_warn};
  46. void tds_set_version(TDSLOGIN *tds_login, short major_ver, short minor_ver)
  47. {
  48.     tds_login->major_version=major_ver;
  49.     tds_login->minor_version=minor_ver;
  50. }
  51. void tds_set_packet(TDSLOGIN *tds_login, short packet_size)
  52.     tds_login->block_size=packet_size; 
  53. }
  54. void tds_set_port(TDSLOGIN *tds_login, int port)
  55.     tds_login->port=port; 
  56. }
  57. void tds_set_passwd(TDSLOGIN *tds_login, char *password)
  58.     if (password) {
  59.         strncpy(tds_login->password, password, sizeof(tds_login->password)-1);
  60.     }
  61. }
  62. void tds_set_bulk(TDSLOGIN *tds_login, TDS_TINYINT enabled)
  63. {
  64.     tds_login->bulk_copy = enabled ? 0 : 1;
  65. }
  66. void tds_set_user(TDSLOGIN *tds_login, char *username)
  67.     strncpy(tds_login->user_name, username, TDS_MAX_LOGIN_STR_SZ);
  68. }
  69. void tds_set_host(TDSLOGIN *tds_login, char *hostname)
  70. {
  71.     strncpy(tds_login->host_name, hostname, TDS_MAX_LOGIN_STR_SZ);
  72. }
  73. void tds_set_app(TDSLOGIN *tds_login, char *application)
  74. {
  75.     strncpy(tds_login->app_name, application, TDS_MAX_LOGIN_STR_SZ);
  76. }
  77. void tds_set_server(TDSLOGIN *tds_login, char *server)
  78. {
  79.     if(!server || strlen(server) == 0) {
  80.         server = getenv("DSQUERY");
  81.         if(!server || strlen(server) == 0) {
  82.             server = "SYBASE";
  83.         }
  84.     }
  85.     strncpy(tds_login->server_name, server, TDS_MAX_LOGIN_STR_SZ);
  86. }
  87. void tds_set_library(TDSLOGIN *tds_login, char *library)
  88. {
  89.     strncpy(tds_login->library, library, TDS_MAX_LIBRARY_STR_SZ);
  90. }
  91. void tds_set_charset(TDSLOGIN *tds_login, char *charset)
  92. {
  93.     strncpy(tds_login->char_set, charset, TDS_MAX_LOGIN_STR_SZ);
  94. }
  95. void tds_set_language(TDSLOGIN *tds_login, char *language)
  96. {
  97.     strncpy(tds_login->language, language, TDS_MAX_LOGIN_STR_SZ);
  98. }
  99. void tds_set_timeouts(TDSLOGIN *tds_login, int connect, int query, int longquery)                   /* Jeffs' hack to support timeouts */
  100. {
  101.     tds_login->connect_timeout = connect;
  102.     tds_login->query_timeout = query;
  103.     tds_login->longquery_timeout = longquery;
  104. }
  105. void tds_set_longquery_handler(TDSLOGIN * tds_login, void (*longquery_func)(long), long longquery_param) /* Jeff's hack */
  106. {
  107.     tds_login->longquery_func = longquery_func;
  108.     tds_login->longquery_param = longquery_param;
  109. }
  110. void tds_set_capabilities(TDSLOGIN *tds_login, unsigned char *capabilities, int size)
  111. {
  112.     memcpy(tds_login->capabilities, capabilities, 
  113.            size > TDS_MAX_CAPABILITY ? TDS_MAX_CAPABILITY : size);
  114. }
  115. #ifdef NCBI_FTDS
  116. TDSSOCKET *tds_connect(TDSLOGIN *login, TDSCONTEXT *context, void *parent) 
  117. {
  118.     TDSSOCKET *tds;
  119.     struct sockaddr_in      sin;
  120.     /* Jeff's hack - begin */
  121.     unsigned long ioctl_blocking = 1;                      
  122.     struct timeval selecttimeout;                         
  123.     fd_set fds;                                          
  124.     fd_set fds1;                                          
  125.     int retval, n;                                         
  126.     time_t start, now;
  127.     TDSCONFIGINFO *config;
  128.     /* 13 + max string of 32bit int, 30 should cover it */
  129.     char query[30];
  130.     char *tmpstr;
  131.     int connect_timeout = 0;
  132.     FD_ZERO (&fds);                                    
  133.     FD_ZERO (&fds1);                                    
  134.     /* end */
  135.     config = tds_get_config(NULL, login, context->locale);
  136.     /*
  137.     ** If a dump file has been specified, start logging
  138.     */
  139.     if (config->dump_file) {
  140.         tdsdump_open(config->dump_file);
  141.     }
  142.     /* 
  143.     ** The initial login packet must have a block size of 512.
  144.     ** Once the connection is established the block size can be changed
  145.     ** by the server with TDS_ENV_CHG_TOKEN
  146.     */
  147.     tds = tds_alloc_socket(context, 512);
  148.     tds_set_parent(tds, parent);
  149.     tds->config = config;
  150.     tds->major_version=config->major_version;
  151.     tds->minor_version=config->minor_version;
  152.     tds->emul_little_endian=config->emul_little_endian;
  153. #ifdef WORDS_BIGENDIAN
  154.     if (IS_TDS70(tds) || IS_TDS80(tds)) {
  155.         /* TDS 7/8 only supports little endian */
  156.         tds->emul_little_endian=1;
  157.     }
  158. #endif
  159.     /* set up iconv */
  160.     if (config->client_charset) {
  161.         tds_iconv_open(tds, config->client_charset);
  162.     }
  163.     /* specified a date format? */
  164.     /*
  165.       if (config->date_fmt) {
  166. tds->date_fmt=strdup(config->date_fmt);
  167.       }
  168.     */
  169.     if (login->connect_timeout) {
  170.         connect_timeout = login->connect_timeout;
  171.     } else if (config->connect_timeout) {
  172.         connect_timeout = config->connect_timeout;
  173.     }
  174.     /* Jeff's hack - begin */
  175.     tds->timeout = login->query_timeout;        
  176.     tds->longquery_timeout = login->longquery_timeout;
  177.     tds->longquery_func = login->longquery_func;
  178.     tds->longquery_param = login->longquery_param;
  179.     /* end */
  180.     /* verify that ip_addr is not NULL */
  181.     if (!config->ip_addr[0]) {
  182.         tdsdump_log(TDS_DBG_ERROR, "%L IP address pointer is NULLn");
  183.         if (config->server_name) {
  184.             tmpstr = malloc(strlen(config->server_name)+100);
  185.             if (tmpstr) {
  186.                 sprintf(tmpstr,"Server %s not found!",config->server_name);
  187.                 tds_client_msg(tds->tds_ctx, tds, 10019, 9, 0, 0, tmpstr);
  188.                 free(tmpstr);
  189.             }
  190.         } else {
  191.             tds_client_msg(tds->tds_ctx, tds, 10020, 9, 0, 0, "No server specified!");
  192.         }
  193.         tds_free_config(config);
  194.         tds_free_socket(tds);
  195.         return NULL;
  196.     }
  197.     memcpy(tds->capabilities,login->capabilities,TDS_MAX_CAPABILITY);
  198. for(n= 0; n < NCBI_NUM_SERVERS; n++) {
  199.     if(config->ip_addr[n] == NULL) {
  200.     /* no more servers */
  201.     tds_client_msg(tds->tds_ctx, tds, 20009, 9, 0, 0, 
  202.    "Server is unavailable or does not exist.");
  203. tds_free_config(config);
  204. tds_free_socket(tds);
  205. return NULL;
  206.         }
  207.     sin.sin_addr.s_addr = inet_addr(config->ip_addr[n]);
  208. if (sin.sin_addr.s_addr == -1) {
  209.     tdsdump_log(TDS_DBG_ERROR, "%L inet_addr() failed, IP = %sn", config->ip_addr[n]);
  210. continue;
  211. }
  212. sin.sin_family = AF_INET;
  213. sin.sin_port = htons(config->port[n]);
  214. tdsdump_log(TDS_DBG_INFO1, "%L Connecting addr %s port %dn", 
  215. inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
  216. if ((tds->s = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
  217.     perror ("socket");
  218. tds_free_config(config);
  219. tds_free_socket(tds);
  220. return NULL;
  221. }
  222.         ioctl_blocking = 1; /* ~0; //TRUE; */
  223.         if (IOCTL(tds->s, FIONBIO, &ioctl_blocking) < 0) {
  224.     tds_free_config(config);
  225.             tds_free_socket(tds);
  226.             return NULL;
  227.         }
  228.         retval = connect(tds->s, (struct sockaddr *) &sin, sizeof(sin));
  229.         if (retval < 0 && errno == EINPROGRESS) retval = 0;
  230.         if (retval < 0) {
  231.     close(tds->s);
  232.     continue;
  233.         }
  234.         /* Select on writeability for connect_timeout */
  235. FD_ZERO (&fds);                                    
  236. FD_ZERO (&fds1);                                    
  237.         for(retval= -1; retval < 0;) {
  238.             selecttimeout.tv_sec = connect_timeout;
  239.             selecttimeout.tv_usec = 0;
  240.             FD_SET (tds->s, &fds);
  241.             FD_SET (tds->s, &fds1);
  242.             retval = select(tds->s + 1, NULL, &fds, &fds1, 
  243.                             (connect_timeout > 0)? &selecttimeout : NULL);
  244.             if((retval < 0) && (errno != EINTR)) {
  245.     break;
  246.             }
  247.         }
  248. if(retval > 0) {
  249.   int r, r_len= sizeof(r);
  250.   if(FD_ISSET(tds->s, &fds1)) retval= -1;
  251.   if(getsockopt(tds->s, SOL_SOCKET, SO_ERROR, &r, &r_len) < 0 ||
  252.  r != 0) retval= -1;
  253. }
  254.         if(retval > 0)
  255.   break;
  256. close(tds->s);
  257. tds->s= 0;
  258. }
  259. if(n >= NCBI_NUM_SERVERS) {
  260. tds_client_msg(tds->tds_ctx, tds, 20009, 9, 0, 0, 
  261.    "Server is unavailable or does not exist.");
  262. tds_free_config(config);
  263. tds_free_socket(tds);
  264. return NULL;
  265. }
  266.     if (IS_TDS7_PLUS(tds)) {
  267.         tds->out_flag=0x10;
  268.         tds7_send_login(tds,config);
  269.     } else {
  270.         tds->out_flag=0x02;
  271.         tds_send_login(tds,config);
  272.     }
  273.     if (!tds_process_login_tokens(tds)) {
  274.         tds_client_msg(tds->tds_ctx, tds, 20014, 9, 0, 0, 
  275.                        "Login incorrect.");
  276.         tds_free_config(config);
  277.         tds_free_socket(tds);
  278.         tds = NULL;
  279.         return NULL;
  280.     }
  281.     if (tds && config->text_size) {
  282.         sprintf(query,"set textsize %d", config->text_size);
  283.         retval = tds_submit_query(tds,query);
  284.         if (retval == TDS_SUCCEED) {
  285.     while (tds_process_result_tokens(tds)==TDS_SUCCEED);
  286.         }
  287.     }
  288.     tds->config = NULL;
  289.     tds_free_config(config);
  290.     return tds;
  291. }
  292. #else
  293. TDSSOCKET *tds_connect(TDSLOGIN *login, TDSCONTEXT *context, void *parent) 
  294. {
  295.     TDSSOCKET *tds;
  296.     struct sockaddr_in      sin;
  297.     /* Jeff's hack - begin */
  298.     unsigned long ioctl_blocking = 1;                      
  299.     struct timeval selecttimeout;                         
  300.     fd_set fds;                                          
  301.     int retval;                                         
  302.     time_t start, now;
  303.     TDSCONFIGINFO *config;
  304.     /* 13 + max string of 32bit int, 30 should cover it */
  305.     char query[30];
  306.     char *tmpstr;
  307.     int connect_timeout = 0;
  308.     FD_ZERO (&fds);                                    
  309.     /* end */
  310.     config = tds_get_config(NULL, login, context->locale);
  311.     /*
  312.     ** If a dump file has been specified, start logging
  313.     */
  314.     if (config->dump_file) {
  315.         tdsdump_open(config->dump_file);
  316.     }
  317.     /* 
  318.     ** The initial login packet must have a block size of 512.
  319.     ** Once the connection is established the block size can be changed
  320.     ** by the server with TDS_ENV_CHG_TOKEN
  321.     */
  322.     tds = tds_alloc_socket(context, 512);
  323.     tds_set_parent(tds, parent);
  324.     tds->config = config;
  325.     tds->major_version=config->major_version;
  326.     tds->minor_version=config->minor_version;
  327.     tds->emul_little_endian=config->emul_little_endian;
  328. #ifdef WORDS_BIGENDIAN
  329.     if (IS_TDS70(tds) || IS_TDS80(tds)) {
  330.         /* TDS 7/8 only supports little endian */
  331.         tds->emul_little_endian=1;
  332.     }
  333. #endif
  334.     /* set up iconv */
  335.     if (config->client_charset) {
  336.         tds_iconv_open(tds, config->client_charset);
  337.     }
  338.     /* specified a date format? */
  339.     /*
  340.       if (config->date_fmt) {
  341. tds->date_fmt=strdup(config->date_fmt);
  342.       }
  343.     */
  344.     if (login->connect_timeout) {
  345.         connect_timeout = login->connect_timeout;
  346.     } else if (config->connect_timeout) {
  347.         connect_timeout = config->connect_timeout;
  348.     }
  349.     /* Jeff's hack - begin */
  350.     tds->timeout = (connect_timeout) ? login->query_timeout : 0;        
  351.     tds->longquery_timeout = (connect_timeout) ? login->longquery_timeout : 0;
  352.     tds->longquery_func = login->longquery_func;
  353.     tds->longquery_param = login->longquery_param;
  354.     /* end */
  355.     /* verify that ip_addr is not NULL */
  356.     if (!config->ip_addr) {
  357.         tdsdump_log(TDS_DBG_ERROR, "%L IP address pointer is NULLn");
  358.         if (config->server_name) {
  359.             tmpstr = malloc(strlen(config->server_name)+100);
  360.             if (tmpstr) {
  361.                 sprintf(tmpstr,"Server %s not found!",config->server_name);
  362.                 tds_client_msg(tds->tds_ctx, tds, 10019, 9, 0, 0, tmpstr);
  363.                 free(tmpstr);
  364.             }
  365.         } else {
  366.             tds_client_msg(tds->tds_ctx, tds, 10020, 9, 0, 0, "No server specified!");
  367.         }
  368.         tds_free_config(config);
  369.         tds_free_socket(tds);
  370.         return NULL;
  371.     }
  372.     sin.sin_addr.s_addr = inet_addr(config->ip_addr);
  373.     if (sin.sin_addr.s_addr == -1) {
  374.         tdsdump_log(TDS_DBG_ERROR, "%L inet_addr() failed, IP = %sn", config->ip_addr);
  375.         tds_free_config(config);
  376.         tds_free_socket(tds);
  377.         return NULL;
  378.     }
  379.     sin.sin_family = AF_INET;
  380.     sin.sin_port = htons(config->port);
  381.     memcpy(tds->capabilities,login->capabilities,TDS_MAX_CAPABILITY);
  382.     tdsdump_log(TDS_DBG_INFO1, "%L Connecting addr %s port %dn", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
  383.     if ((tds->s = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
  384.         perror ("socket");
  385.         tds_free_config(config);
  386.         tds_free_socket(tds);
  387.         return NULL;
  388.     }
  389.     /* Jeff's hack *** START OF NEW CODE *** */
  390.     if (connect_timeout) {
  391.         start = time (NULL);
  392.         ioctl_blocking = 1; /* ~0; //TRUE; */
  393.         if (IOCTL(tds->s, FIONBIO, &ioctl_blocking) < 0) {
  394.             tds_free_config(config);
  395.             tds_free_socket(tds);
  396.             return NULL;
  397.         }
  398.         retval = connect(tds->s, (struct sockaddr *) &sin, sizeof(sin));
  399.         if (retval < 0 && errno == EINPROGRESS) retval = 0;
  400.         if (retval < 0) {
  401.             tds_client_msg(tds->tds_ctx, tds, 20009, 9, 0, 0, 
  402.                            "Server is unavailable or does not exist.");
  403.             tds_free_config(config);
  404.             tds_free_socket(tds);
  405.             return NULL;
  406.         }
  407.         /* Select on writeability for connect_timeout */
  408.         now = start;
  409.         while ((retval == 0) && ((now-start) < connect_timeout)) {
  410.             FD_SET (tds->s, &fds);
  411.             selecttimeout.tv_sec = connect_timeout - (now-start);
  412.             selecttimeout.tv_usec = 0;
  413.             retval = select(tds->s + 1, NULL, &fds, NULL, &selecttimeout);
  414.             if (retval < 0 && errno == EINTR)
  415.                 retval = 0;
  416.             now = time (NULL);
  417.         }
  418.         if ((now-start) > connect_timeout) {
  419.             tds_client_msg(tds->tds_ctx, tds, 20009, 9, 0, 0, 
  420.                            "Server is unavailable or does not exist.");
  421.             tds_free_config(config);
  422.             tds_free_socket(tds);
  423.             return NULL;
  424.         }
  425.     } else {
  426.         if (connect(tds->s, (struct sockaddr *) &sin, sizeof(sin)) <0) {
  427.             char message[128];
  428.             sprintf(message, "src/tds/login.c: tds_connect: %s:%d",
  429.                     inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
  430.             perror(message);
  431.             tds_client_msg(tds->tds_ctx, tds, 20009, 9, 0, 0, 
  432.                            "Server is unavailable or does not exist.");
  433.             tds_free_config(config);
  434.             tds_free_socket(tds);
  435.             return NULL;
  436.         }
  437.     }
  438.     /* END OF NEW CODE */
  439.     if (IS_TDS7_PLUS(tds)) {
  440.         tds->out_flag=0x10;
  441.         tds7_send_login(tds,config);
  442.     } else {
  443.         tds->out_flag=0x02;
  444.         tds_send_login(tds,config);
  445.     }
  446.     if (!tds_process_login_tokens(tds)) {
  447.         tds_client_msg(tds->tds_ctx, tds, 20014, 9, 0, 0, 
  448.                        "Login incorrect.");
  449.         tds_free_config(config);
  450.         tds_free_socket(tds);
  451.         tds = NULL;
  452.         return NULL;
  453.     }
  454.     if (tds && config->text_size) {
  455.         sprintf(query,"set textsize %d", config->text_size);
  456.         retval = tds_submit_query(tds,query);
  457.         if (retval == TDS_SUCCEED) {
  458.     while (tds_process_result_tokens(tds)==TDS_SUCCEED);
  459.         }
  460.     }
  461.     tds->config = NULL;
  462.     tds_free_config(config);
  463.     return tds;
  464. }
  465. #endif
  466. int tds_send_login(TDSSOCKET *tds, TDSCONFIGINFO *config)
  467. {
  468.     /*   char *tmpbuf;
  469.          int tmplen;*/
  470. #ifdef WORDS_BIGENDIAN
  471.     unsigned char be1[]= {0x02,0x00,0x06,0x04,0x08,0x01};
  472. #endif
  473.     unsigned char le1[]= {0x03,0x01,0x06,0x0a,0x09,0x01};
  474.     unsigned char magic2[]={0x00,0x00};
  475.    
  476.     unsigned char magic3[]= {0x00,0x00,0x00};
  477.    
  478. /* these seem to endian flags as well 13,17 on intel/alpha 12,16 on power */
  479.    
  480. #ifdef WORDS_BIGENDIAN
  481.     unsigned char be2[]= {0x00,12,16};
  482. #endif
  483.     unsigned char le2[]= {0x00,13,17};
  484.    
  485.    /* 
  486.    ** the former byte 0 of magic5 causes the language token and message to be 
  487.    ** absent from the login acknowledgement if set to 1. There must be a way 
  488.    ** of setting this in the client layer, but I am not aware of any thing of
  489.    ** the sort -- bsb 01/17/99
  490.    */
  491.     unsigned char magic5[]= {0x00,0x00};
  492.     unsigned char magic6[]= {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
  493.     unsigned char magic7=   0x01;
  494.    
  495.     unsigned char magic42[]= {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
  496.     unsigned char magic50[]= {0x00,0x00,0x00,0x00};
  497.     /*
  498. ** capabilities are now part of the tds structure.
  499.    unsigned char capabilities[]= {0x01,0x07,0x03,109,127,0xFF,0xFF,0xFF,0xFE,0x02,0x07,0x00,0x00,0x0A,104,0x00,0x00,0x00};
  500. */
  501. /*
  502. ** This is the original capabilities packet we were working with (sqsh)
  503.    unsigned char capabilities[]= {0x01,0x07,0x03,109,127,0xFF,0xFF,0xFF,0xFE,0x02,0x07,0x00,0x00,0x0A,104,0x00,0x00,0x00};
  504. ** original with 4.x messages
  505.    unsigned char capabilities[]= {0x01,0x07,0x03,109,127,0xFF,0xFF,0xFF,0xFE,0x02,0x07,0x00,0x00,0x00,120,192,0x00,0x0D};
  506. ** This is isql 11.0.3
  507.    unsigned char capabilities[]= {0x01,0x07,0x00,96, 129,207, 0xFF,0xFE,62,  0x02,0x07,0x00,0x00,0x00,120,192,0x00,0x0D};
  508. ** like isql but with 5.0 messages
  509.    unsigned char capabilities[]= {0x01,0x07,0x00,96, 129,207, 0xFF,0xFE,62,  0x02,0x07,0x00,0x00,0x00,120,192,0x00,0x00};
  510. **
  511. */
  512.    
  513.     unsigned char protocol_version[4];
  514.     unsigned char program_version[4];
  515.    
  516.     int rc;
  517.     char blockstr[10], passwdstr[255];
  518.    
  519.     if (IS_TDS42(tds)) {
  520.         memcpy(protocol_version,"04020000",4);
  521.         memcpy(program_version,"04020000",4);
  522.     } else if (IS_TDS46(tds)) {
  523.         memcpy(protocol_version,"04060000",4);
  524.         memcpy(program_version,"04020000",4);
  525.     } else if (IS_TDS50(tds)) {
  526.         memcpy(protocol_version,"05000000",4);
  527.         memcpy(program_version,"05000000",4);
  528.     } else {
  529.         tdsdump_log(TDS_DBG_SEVERE,"Unknown protocol version!n");
  530.         exit(1);
  531.     }
  532.     /*
  533.    ** the following code is adapted from  Arno Pedusaar's 
  534.    ** (psaar@fenar.ee) MS-SQL Client. His was a much better way to
  535.    ** do this, (well...mine was a kludge actually) so here's mostly his
  536.    */
  537.    
  538.     rc=tds_put_string(tds,config->host_name,TDS_MAX_LOGIN_STR_SZ);   /* client host name */
  539.     rc|=tds_put_string(tds,config->user_name,TDS_MAX_LOGIN_STR_SZ);  /* account name */
  540.     rc|=tds_put_string(tds,config->password,TDS_MAX_LOGIN_STR_SZ);  /* account password */
  541.     //rc|=tds_put_string(tds,"37876",TDS_MAX_LOGIN_STR_SZ);        /* host process */
  542.     rc|=tds_put_string(tds,"11111",TDS_MAX_LOGIN_STR_SZ);        /* host process */
  543. #ifdef WORDS_BIGENDIAN
  544.     if (tds->emul_little_endian) {
  545.         rc|=tds_put_n(tds,le1,6);
  546.     } else {
  547.         rc|=tds_put_n(tds,be1,6);
  548.     }
  549. #else
  550.     rc|=tds_put_n(tds,le1,6);
  551. #endif
  552.     rc|=tds_put_byte(tds,config->bulk_copy);
  553.     rc|=tds_put_n(tds,magic2,2);
  554.     if (IS_TDS42(tds)) {
  555.         rc|=tds_put_int(tds,512);
  556.     } else {
  557.         rc|=tds_put_int(tds,0);
  558.     }
  559.     rc|=tds_put_n(tds,magic3,3);
  560.     rc|=tds_put_string(tds,config->app_name,TDS_MAX_LOGIN_STR_SZ);
  561.     rc|=tds_put_string(tds,config->server_name,TDS_MAX_LOGIN_STR_SZ);
  562.     if (IS_TDS42(tds)) {
  563.         rc|=tds_put_string(tds,config->password,255);
  564.     } else {
  565.         if(config->password == NULL) {
  566.             sprintf(passwdstr, "%c%c%s", 0, 0, "");
  567.             rc|=tds_put_buf(tds,passwdstr,255,(unsigned char)2);
  568.         } else {
  569.             sprintf(passwdstr,"%c%c%s",0,
  570.                     (unsigned char)strlen(config->password),
  571.                     config->password);
  572.             rc|=tds_put_buf(tds,passwdstr,255,(unsigned char)strlen(config->password)+2);
  573.         }
  574.     }
  575.    
  576.     rc|=tds_put_n(tds,protocol_version,4); /* TDS version; { 0x04,0x02,0x00,0x00 } */
  577.     rc|=tds_put_string(tds,config->library,10);  /* client program name */
  578.     if (IS_TDS42(tds)) { 
  579.         rc|=tds_put_int(tds,0);
  580.     } else {
  581.         rc|=tds_put_n(tds,program_version,4); /* program version ? */
  582.     }
  583. #ifdef WORDS_BIGENDIAN
  584.     if (tds->emul_little_endian) {
  585.         rc|=tds_put_n(tds,le2,3);
  586.     } else {
  587.         rc|=tds_put_n(tds,be2,3);
  588.     }
  589. #else
  590.     rc|=tds_put_n(tds,le2,3);
  591. #endif
  592.     rc|=tds_put_string(tds,config->language,TDS_MAX_LOGIN_STR_SZ);  /* language */
  593.     rc|=tds_put_byte(tds,config->suppress_language);
  594.     rc|=tds_put_n(tds,magic5,2);
  595.     rc|=tds_put_byte(tds,config->encrypted);
  596.     rc|=tds_put_n(tds,magic6,10);
  597.     rc|=tds_put_string(tds,config->char_set,TDS_MAX_LOGIN_STR_SZ);  /* charset */
  598.     rc|=tds_put_byte(tds,magic7);
  599.     sprintf(blockstr,"%d",config->block_size);
  600.     rc|=tds_put_string(tds,blockstr,6); /* network packet size */
  601.     if (IS_TDS42(tds)) {
  602.         rc|=tds_put_n(tds,magic42,8);
  603.     } else if (IS_TDS46(tds)) {
  604.         rc|=tds_put_n(tds,magic42,4);
  605.     } else if (IS_TDS50(tds)) {
  606.         rc|=tds_put_n(tds,magic50,4);
  607.         rc|=tds_put_byte(tds, TDS_CAP_TOKEN);
  608.         rc|=tds_put_smallint(tds, 18);
  609.         rc|=tds_put_n(tds,tds->capabilities,TDS_MAX_CAPABILITY);
  610.     }
  611.    
  612.     /*
  613.    tmpbuf = malloc(tds->out_pos);
  614.    tmplen = tds->out_pos;
  615.    memcpy(tmpbuf, tds->out_buf, tmplen);
  616.    tdsdump_off();
  617. */
  618.     rc|=tds_flush_packet(tds);
  619.     /*
  620.    tdsdump_on();
  621.    tdsdump_log(TDS_DBG_NETWORK, "Sending packet (passwords supressed)@ %Ln%Dn", tmpbuf, tmplen);
  622.    free(tmpbuf);
  623. */
  624.    /* get_incoming(tds->s); */
  625.     return 0;
  626. }
  627. int tds7_send_auth(TDSSOCKET *tds, unsigned char *challenge)
  628. {
  629. #if DOMAIN
  630.     int rc;
  631.     int current_pos;
  632.     TDSANSWER answer;
  633.     /* FIXME: stuff duplicate in tds7_send_login */
  634.     const char* domain;
  635.     const char* user_name;
  636.     const char* p;
  637.     int user_name_len;
  638.     int host_name_len;
  639.     int password_len;
  640.     int domain_len;
  641.     unsigned char unicode_string[256];
  642.     TDSCONFIGINFO *config = tds->config;
  643.     /* check config */
  644.     if (!config)
  645.         return TDS_FAIL;
  646.     /* parse a bit of config */
  647.     domain = config->default_domain;
  648.     user_name = config->user_name;
  649.     user_name_len = user_name ? strlen(user_name) : 0;
  650.     host_name_len = config->host_name ? strlen(config->host_name) : 0;
  651.     password_len = config->password ? strlen(config->password) : 0;
  652.     domain_len = domain ? strlen(domain) : 0;
  653.     /* check override of domain */
  654.     if (user_name && (p=strchr(user_name,'\')) != NULL)
  655.         {
  656.             domain = user_name;
  657.             domain_len = p-user_name;
  658.             user_name = p+1;
  659.             user_name_len = strlen(user_name);
  660.         }
  661.     tds->out_flag=0x11;
  662.     tds_put_n(tds, "NTLMSSP", 8);
  663.     tds_put_int(tds, 3); /* sequence 3 */
  664.     current_pos = 64 + (domain_len+user_name_len+host_name_len)*2;
  665.     tds_put_smallint(tds, 24);  /* lan man resp length */
  666.     tds_put_smallint(tds, 24);  /* lan man resp length */
  667.     tds_put_int(tds, current_pos);  /* resp offset */
  668.     current_pos += 24;
  669.     tds_put_smallint(tds, 24);  /* nt resp length */
  670.     tds_put_smallint(tds, 24);  /* nt resp length */
  671.     tds_put_int(tds, current_pos);  /* nt resp offset */
  672.     current_pos = 64;
  673.     /* domain */
  674.     tds_put_smallint(tds, domain_len*2);
  675.     tds_put_smallint(tds, domain_len*2);
  676.     tds_put_int(tds, current_pos);
  677.     current_pos += domain_len*2;
  678.     /* username */
  679.     tds_put_smallint(tds, user_name_len*2);
  680.     tds_put_smallint(tds, user_name_len*2);
  681.     tds_put_int(tds, current_pos);
  682.     current_pos += user_name_len*2;
  683.     /* hostname */
  684.     tds_put_smallint(tds, host_name_len*2);
  685.     tds_put_smallint(tds, host_name_len*2);
  686.     tds_put_int(tds, current_pos);
  687.     current_pos += host_name_len*2;
  688.     /* unknown */
  689.     tds_put_smallint(tds, 0);
  690.     tds_put_smallint(tds, 0);
  691.     tds_put_int(tds, current_pos + (24*2));
  692.     /* flags */
  693.     tds_put_int(tds,0x8201);
  694.     tds7_ascii2unicode(tds,domain, unicode_string, 256);
  695.     tds_put_n(tds,unicode_string,domain_len * 2);
  696.     tds7_ascii2unicode(tds,user_name, unicode_string, 256);
  697.     tds_put_n(tds,unicode_string,user_name_len * 2);
  698.     tds7_ascii2unicode(tds,config->host_name, unicode_string, 256);
  699.     tds_put_n(tds,unicode_string,host_name_len * 2);
  700.     tds_answer_challenge(config->password, challenge, &answer);
  701.     tds_put_n(tds, answer.lm_resp, 24);
  702.     tds_put_n(tds, answer.nt_resp, 24);
  703.     /* for security reason clear structure */
  704.     memset(&answer,0,sizeof(TDSANSWER));
  705.     rc=tds_flush_packet(tds);
  706.     return rc;
  707. #else
  708.     return TDS_SUCCEED;
  709. #endif
  710. }
  711. /*
  712. ** tds7_send_login() -- Send a TDS 7.0 login packet
  713. ** TDS 7.0 login packet is vastly different and so gets its own function
  714. */
  715. int tds7_send_login(TDSSOCKET *tds, TDSCONFIGINFO *config)
  716. {
  717.     int rc;
  718. #if DOMAIN
  719.     static const unsigned char magic1_domain[] =
  720.     {6,0x7d,0x0f,0xfd,
  721.      0xff,0x0,0x0,0x0,  /* Client PID */
  722.      /* the 0x80 in the third byte controls whether this is a domain login 
  723.       * or not  0x80 = yes, 0x00 = no */
  724.      0x0,0xe0,0x83,0x0, /* Connection ID of the Primary Server (?) */
  725.      0x0,               /* Option Flags 1 */
  726.      0x68,              /* Option Flags 2 */
  727.      0x01,
  728.      0x00,
  729.      0x00,0x09,0x04,0x00,
  730.      0x00};
  731. #endif
  732.     static const unsigned char magic1_server[] =
  733.     {6,0x83,0xf2,0xf8,  /* Client Program version */
  734.      0xff,0x0,0x0,0x0,  /* Client PID */
  735.      0x0,0xe0,0x03,0x0, /* Connection ID of the Primary Server (?) */
  736.      0x0,               /* Option Flags 1 */
  737.      0x88,              /* Option Flags 2 */
  738.      0xff,              /* Type Flags     */
  739.      0xff,              /* reserved Flags */
  740.      0xff,0x36,0x04,0x00,
  741.      0x00};
  742.     unsigned const char *magic1 = magic1_server;
  743. #if 0
  744.     /* also seen */
  745.     {6,0x7d,0x0f,0xfd,
  746.          0xff,0x0,0x0,0x0,
  747.          0x0,0xe0,0x83,0x0,
  748.          0x0,
  749.          0x68,
  750.          0x01,
  751.          0x00,
  752.          0x00,0x09,0x04,0x00,
  753.          0x00};
  754. #endif
  755.     static const unsigned char magic2[] = {0x00,0x40,0x33,0x9a,0x6b,0x50};
  756.     /* 0xb4,0x00,0x30,0x00,0xe4,0x00,0x00,0x00; */
  757.     static const unsigned char magic3[] = "NTLMSSP";
  758.     unsigned char unicode_string[255];
  759.     int packet_size;
  760.     int current_pos;
  761. #if DOMAIN
  762.     int domain_login = config->try_domain_login ? 1 : 0;
  763. #endif
  764.     const char* domain = config->default_domain;
  765.     const char* user_name = config->user_name;
  766.     const char* p;
  767.     int user_name_len = user_name ? strlen(user_name) : 0;
  768.     int host_name_len = config->host_name ? strlen(config->host_name) : 0;
  769.     int app_name_len = config->app_name ? strlen(config->app_name) : 0;
  770.     int password_len = config->password ? strlen(config->password) : 0;
  771.     int server_name_len = config->server_name ? strlen(config->server_name) : 0;
  772.     int library_len = config->library ? strlen(config->library) : 0;
  773.     int language_len = config->language ? strlen(config->language) : 0;
  774.     int domain_len = domain ? strlen(domain) : 0;
  775.     int auth_len = 0;
  776.     /* check override of domain */
  777.     if (user_name && (p=strchr(user_name,'\')) != NULL)
  778.         {
  779.             domain = user_name;
  780.             domain_len = p-user_name;
  781.             user_name = p+1;
  782.             user_name_len = strlen(user_name);
  783.         }
  784.     packet_size = 86 + (
  785.                         host_name_len +
  786.                         app_name_len +
  787.                         server_name_len +
  788.                         library_len +
  789.                         language_len)*2;
  790. #if DOMAIN
  791.     if (domain_login) {
  792.         magic1 = magic1_domain;
  793.         auth_len = 32 + host_name_len + domain_len;
  794.         packet_size += auth_len;
  795.     } else
  796. #endif
  797.         packet_size += (user_name_len + password_len)*2;
  798. #ifdef NCBI_FTDS
  799. tds_put_int(tds, packet_size);
  800. if (IS_TDS80(tds)) {
  801.   static const unsigned char tds8Version[] = { 0x01, 0x00, 0x00, 0x71 };
  802. tds_put_n(tds, tds8Version, 4);
  803. } else {
  804.   static const unsigned char tds7Version[] = { 0x00, 0x00, 0x00, 0x70 };
  805. tds_put_n(tds, tds7Version, 4);
  806. }
  807. #else
  808.     tds_put_smallint(tds,packet_size);
  809.     tds_put_n(tds,NULL,5);
  810.     if (IS_TDS80(tds)) {
  811.         tds_put_byte(tds,0x80);
  812.     } else {
  813.         tds_put_byte(tds,0x70);
  814.     }
  815.     tds_put_n(tds,NULL,3);       /* rest of TDSVersion which is a 4 byte field    */
  816. #endif
  817. #ifdef NCBI_FTDS
  818. if(config->block_size < 512 || config->block_size > 1000000) 
  819.   config->block_size= 4096;
  820. tds_put_int(tds, config->block_size);
  821. tds_put_n(tds, magic1, 4); /* client program version ? */
  822. packet_size= getpid();
  823. tds_put_int(tds, packet_size); /* process id of this process */
  824. /*tds_put_n(tds, magic1+8, 13);*/
  825. #if 1
  826. {
  827. static const unsigned char connection_id[] = { 0x00, 0x00, 0x00, 0x00 };
  828. unsigned char option_flag1 = 0x00;
  829. unsigned char option_flag2 = 0x00;
  830. static const unsigned char sql_type_flag = 0x00;
  831. static const unsigned char reserved_flag = 0x00;
  832. static const unsigned char time_zone[] = { 0x88, 0xff, 0xff, 0xff };
  833. static const unsigned char collation[] = { 0x36, 0x04, 0x00, 0x00 };
  834. tds_put_n(tds, connection_id, 4);
  835. option_flag1 |= 0x80; /* enable warning messages if SET LANGUAGE issued   */
  836. option_flag1 |= 0x40; /* change to initial database must succeed          */
  837. option_flag1 |= 0x20; /* enable warning messages if USE <database> issued */
  838. tds_put_byte(tds, option_flag1);
  839. option_flag2 |= 0x02; /* client is an ODBC driver                         */
  840. option_flag2 |= 0x01; /* change to initial language must succeed          */
  841. tds_put_byte(tds, option_flag2);
  842. tds_put_byte(tds, sql_type_flag);
  843. tds_put_byte(tds, reserved_flag);
  844. tds_put_n(tds, time_zone, 4);
  845. tds_put_n(tds, collation, 4);
  846. }
  847. #endif
  848. #else
  849.     tds_put_n(tds,NULL,4);       /* desired packet size being requested by client */
  850.     tds_put_n(tds,magic1,21);
  851. #endif
  852.     current_pos = 86; /* ? */
  853.     /* host name */
  854.     tds_put_smallint(tds,current_pos); 
  855.     tds_put_smallint(tds,host_name_len);
  856.     current_pos += host_name_len * 2;
  857. #if DOMAIN
  858.     if (domain_login) {
  859.         tds_put_smallint(tds,0);
  860.         tds_put_smallint(tds,0);
  861.         tds_put_smallint(tds,0);
  862.         tds_put_smallint(tds,0);
  863.     } else {
  864. #endif
  865.         /* username */
  866.         tds_put_smallint(tds,current_pos);
  867.         tds_put_smallint(tds,user_name_len);
  868.         current_pos += user_name_len * 2;
  869.         /* password */
  870.         tds_put_smallint(tds,current_pos);
  871.         tds_put_smallint(tds,password_len);
  872.         current_pos += password_len * 2;
  873. #if DOMAIN
  874.     }
  875. #endif
  876.     /* app name */
  877.     tds_put_smallint(tds,current_pos);
  878.     tds_put_smallint(tds,app_name_len);
  879.     current_pos += app_name_len * 2;
  880.     /* server name */
  881.     tds_put_smallint(tds,current_pos);
  882.     tds_put_smallint(tds,server_name_len);
  883.     current_pos += server_name_len * 2;
  884.     /* unknown */
  885.     tds_put_smallint(tds,0); 
  886.     tds_put_smallint(tds,0); 
  887.     /* library name */
  888.     tds_put_smallint(tds,current_pos);
  889.     tds_put_smallint(tds,library_len);
  890.     current_pos += library_len * 2;
  891.     /* language  - kostya@warmcat.excom.spb.su */
  892.     tds_put_smallint(tds,current_pos); 
  893.     tds_put_smallint(tds,language_len);
  894.     current_pos += language_len * 2;
  895.     /* database name */
  896.     tds_put_smallint(tds,current_pos); 
  897.     tds_put_smallint(tds,0); 
  898.     /* MAC address */
  899.     tds_put_n(tds,magic2,6);
  900.     /* authentication stuff */
  901.     tds_put_smallint(tds, current_pos);
  902. #if DOMAIN
  903.     if (domain_login) {
  904.         tds_put_smallint(tds, auth_len); /* this matches numbers at end of packet */
  905.         current_pos += auth_len;
  906.     } else
  907.         tds_put_smallint(tds, 0);
  908. #else
  909.     tds_put_smallint(tds, 0);
  910. #endif
  911.     /* unknown */
  912.     tds_put_smallint(tds, current_pos);
  913.     tds_put_smallint(tds, 0); 
  914.     tds7_ascii2unicode(tds,config->host_name, unicode_string, 255);
  915.     tds_put_n(tds,unicode_string,host_name_len * 2);
  916. #if DOMAIN
  917.     if (!domain_login) {
  918. #endif
  919.         tds7_ascii2unicode(tds,config->user_name, unicode_string, 255);
  920.         tds_put_n(tds,unicode_string,user_name_len * 2);
  921.         tds7_ascii2unicode(tds,config->password, unicode_string, 255);
  922.         tds7_crypt_pass(unicode_string, password_len * 2, unicode_string);
  923.         tds_put_n(tds,unicode_string,password_len * 2);
  924. #if DOMAIN
  925.     }
  926. #endif
  927.     tds7_ascii2unicode(tds,config->app_name, unicode_string, 255);
  928.     tds_put_n(tds,unicode_string,app_name_len * 2);
  929.     tds7_ascii2unicode(tds,config->server_name, unicode_string, 255);
  930.     tds_put_n(tds,unicode_string,server_name_len * 2);
  931.     tds7_ascii2unicode(tds,config->library, unicode_string, 255);
  932.     tds_put_n(tds,unicode_string,library_len * 2);
  933.     tds7_ascii2unicode(tds,config->language, unicode_string, 255);
  934.     tds_put_n(tds,unicode_string,language_len * 2);
  935. #if DOMAIN
  936.     if (domain_login) {
  937.         /* from here to the end of the packet is the NTLMSSP authentication */
  938.         tds_put_n(tds,magic3,8);
  939.         /* sequence 1 client -> server */
  940.         tds_put_int(tds,1);
  941.         /* flags */
  942.         tds_put_int(tds,0xb201);
  943.         /* domain info */
  944.         tds_put_smallint(tds,domain_len);
  945.         tds_put_smallint(tds,domain_len);
  946.         tds_put_int(tds,32 + host_name_len);
  947.         /* hostname info */
  948.         tds_put_smallint(tds,host_name_len);
  949.         tds_put_smallint(tds,host_name_len);
  950.         tds_put_int(tds,32);
  951.         /* hostname and domain */
  952.         tds_put_n(tds,config->host_name,host_name_len);
  953.         tds_put_n(tds,domain,domain_len);
  954.     }
  955. #endif
  956.    
  957.     tdsdump_off();
  958.     rc=tds_flush_packet(tds);
  959.     tdsdump_on();
  960.    
  961.     return rc;
  962. }
  963. /*
  964. ** tds7_crypt_pass() -- 'encrypt' TDS 7.0 style passwords.
  965. ** the calling function is responsible for ensuring crypt_pass is at least 
  966. ** 'len' characters
  967. */
  968. unsigned char *
  969. tds7_crypt_pass(const unsigned char *clear_pass, int len, unsigned char *crypt_pass)
  970. {
  971.     int i;
  972.     unsigned char xormask = 0x5A;
  973.     unsigned char hi_nibble,lo_nibble ;
  974.     for (i=0;i<len;i++) {
  975.         lo_nibble  = (clear_pass[i] ^ xormask) >> 4;
  976.         hi_nibble  = (clear_pass[i] ^ xormask) << 4;
  977.         crypt_pass[i] = hi_nibble | lo_nibble;
  978.     }
  979.     return crypt_pass;
  980. }