login.c
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:34k
- /*
- * ===========================================================================
- * PRODUCTION $Log: login.c,v $
- * PRODUCTION Revision 1000.0 2003/10/29 20:34:56 gouriano
- * PRODUCTION PRODUCTION: IMPORTED [ORIGINAL] Dev-tree R1.3
- * PRODUCTION
- * ===========================================================================
- */
- /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
- * Copyright (C) 1998-1999 Brian Bruns
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
- #include <tds_config.h>
- #include "tds.h"
- #include "tdsutil.h"
- #ifdef DMALLOC
- #include <dmalloc.h>
- #endif
- #ifdef WIN32
- #define IOCTL(a,b,c) ioctlsocket(a, b, c)
- #else
- #define IOCTL(a,b,c) ioctl(a, b, c)
- #endif
- #ifdef HAVE_SSL
- #define DOMAIN 1
- #else
- #define DOMAIN 0
- #endif
- static char software_version[] = "$Id: login.c,v 1000.0 2003/10/29 20:34:56 gouriano Exp $";
- static void *no_unused_var_warn[] = {software_version,
- no_unused_var_warn};
- void tds_set_version(TDSLOGIN *tds_login, short major_ver, short minor_ver)
- {
- tds_login->major_version=major_ver;
- tds_login->minor_version=minor_ver;
- }
- void tds_set_packet(TDSLOGIN *tds_login, short packet_size)
- {
- tds_login->block_size=packet_size;
- }
- void tds_set_port(TDSLOGIN *tds_login, int port)
- {
- tds_login->port=port;
- }
- void tds_set_passwd(TDSLOGIN *tds_login, char *password)
- {
- if (password) {
- strncpy(tds_login->password, password, sizeof(tds_login->password)-1);
- }
- }
- void tds_set_bulk(TDSLOGIN *tds_login, TDS_TINYINT enabled)
- {
- tds_login->bulk_copy = enabled ? 0 : 1;
- }
- void tds_set_user(TDSLOGIN *tds_login, char *username)
- {
- strncpy(tds_login->user_name, username, TDS_MAX_LOGIN_STR_SZ);
- }
- void tds_set_host(TDSLOGIN *tds_login, char *hostname)
- {
- strncpy(tds_login->host_name, hostname, TDS_MAX_LOGIN_STR_SZ);
- }
- void tds_set_app(TDSLOGIN *tds_login, char *application)
- {
- strncpy(tds_login->app_name, application, TDS_MAX_LOGIN_STR_SZ);
- }
- void tds_set_server(TDSLOGIN *tds_login, char *server)
- {
- if(!server || strlen(server) == 0) {
- server = getenv("DSQUERY");
- if(!server || strlen(server) == 0) {
- server = "SYBASE";
- }
- }
- strncpy(tds_login->server_name, server, TDS_MAX_LOGIN_STR_SZ);
- }
- void tds_set_library(TDSLOGIN *tds_login, char *library)
- {
- strncpy(tds_login->library, library, TDS_MAX_LIBRARY_STR_SZ);
- }
- void tds_set_charset(TDSLOGIN *tds_login, char *charset)
- {
- strncpy(tds_login->char_set, charset, TDS_MAX_LOGIN_STR_SZ);
- }
- void tds_set_language(TDSLOGIN *tds_login, char *language)
- {
- strncpy(tds_login->language, language, TDS_MAX_LOGIN_STR_SZ);
- }
- void tds_set_timeouts(TDSLOGIN *tds_login, int connect, int query, int longquery) /* Jeffs' hack to support timeouts */
- {
- tds_login->connect_timeout = connect;
- tds_login->query_timeout = query;
- tds_login->longquery_timeout = longquery;
- }
- void tds_set_longquery_handler(TDSLOGIN * tds_login, void (*longquery_func)(long), long longquery_param) /* Jeff's hack */
- {
- tds_login->longquery_func = longquery_func;
- tds_login->longquery_param = longquery_param;
- }
- void tds_set_capabilities(TDSLOGIN *tds_login, unsigned char *capabilities, int size)
- {
- memcpy(tds_login->capabilities, capabilities,
- size > TDS_MAX_CAPABILITY ? TDS_MAX_CAPABILITY : size);
- }
- #ifdef NCBI_FTDS
- TDSSOCKET *tds_connect(TDSLOGIN *login, TDSCONTEXT *context, void *parent)
- {
- TDSSOCKET *tds;
- struct sockaddr_in sin;
- /* Jeff's hack - begin */
- unsigned long ioctl_blocking = 1;
- struct timeval selecttimeout;
- fd_set fds;
- fd_set fds1;
- int retval, n;
- time_t start, now;
- TDSCONFIGINFO *config;
- /* 13 + max string of 32bit int, 30 should cover it */
- char query[30];
- char *tmpstr;
- int connect_timeout = 0;
- FD_ZERO (&fds);
- FD_ZERO (&fds1);
- /* end */
- config = tds_get_config(NULL, login, context->locale);
- /*
- ** If a dump file has been specified, start logging
- */
- if (config->dump_file) {
- tdsdump_open(config->dump_file);
- }
- /*
- ** The initial login packet must have a block size of 512.
- ** Once the connection is established the block size can be changed
- ** by the server with TDS_ENV_CHG_TOKEN
- */
- tds = tds_alloc_socket(context, 512);
- tds_set_parent(tds, parent);
- tds->config = config;
- tds->major_version=config->major_version;
- tds->minor_version=config->minor_version;
- tds->emul_little_endian=config->emul_little_endian;
- #ifdef WORDS_BIGENDIAN
- if (IS_TDS70(tds) || IS_TDS80(tds)) {
- /* TDS 7/8 only supports little endian */
- tds->emul_little_endian=1;
- }
- #endif
- /* set up iconv */
- if (config->client_charset) {
- tds_iconv_open(tds, config->client_charset);
- }
- /* specified a date format? */
- /*
- if (config->date_fmt) {
- tds->date_fmt=strdup(config->date_fmt);
- }
- */
- if (login->connect_timeout) {
- connect_timeout = login->connect_timeout;
- } else if (config->connect_timeout) {
- connect_timeout = config->connect_timeout;
- }
- /* Jeff's hack - begin */
- tds->timeout = login->query_timeout;
- tds->longquery_timeout = login->longquery_timeout;
- tds->longquery_func = login->longquery_func;
- tds->longquery_param = login->longquery_param;
- /* end */
- /* verify that ip_addr is not NULL */
- if (!config->ip_addr[0]) {
- tdsdump_log(TDS_DBG_ERROR, "%L IP address pointer is NULLn");
- if (config->server_name) {
- tmpstr = malloc(strlen(config->server_name)+100);
- if (tmpstr) {
- sprintf(tmpstr,"Server %s not found!",config->server_name);
- tds_client_msg(tds->tds_ctx, tds, 10019, 9, 0, 0, tmpstr);
- free(tmpstr);
- }
- } else {
- tds_client_msg(tds->tds_ctx, tds, 10020, 9, 0, 0, "No server specified!");
- }
- tds_free_config(config);
- tds_free_socket(tds);
- return NULL;
- }
- memcpy(tds->capabilities,login->capabilities,TDS_MAX_CAPABILITY);
- for(n= 0; n < NCBI_NUM_SERVERS; n++) {
- if(config->ip_addr[n] == NULL) {
- /* no more servers */
- tds_client_msg(tds->tds_ctx, tds, 20009, 9, 0, 0,
- "Server is unavailable or does not exist.");
- tds_free_config(config);
- tds_free_socket(tds);
- return NULL;
- }
- sin.sin_addr.s_addr = inet_addr(config->ip_addr[n]);
- if (sin.sin_addr.s_addr == -1) {
- tdsdump_log(TDS_DBG_ERROR, "%L inet_addr() failed, IP = %sn", config->ip_addr[n]);
- continue;
- }
- sin.sin_family = AF_INET;
- sin.sin_port = htons(config->port[n]);
- tdsdump_log(TDS_DBG_INFO1, "%L Connecting addr %s port %dn",
- inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
- if ((tds->s = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
- perror ("socket");
- tds_free_config(config);
- tds_free_socket(tds);
- return NULL;
- }
- ioctl_blocking = 1; /* ~0; //TRUE; */
- if (IOCTL(tds->s, FIONBIO, &ioctl_blocking) < 0) {
- tds_free_config(config);
- tds_free_socket(tds);
- return NULL;
- }
- retval = connect(tds->s, (struct sockaddr *) &sin, sizeof(sin));
- if (retval < 0 && errno == EINPROGRESS) retval = 0;
- if (retval < 0) {
- close(tds->s);
- continue;
- }
- /* Select on writeability for connect_timeout */
- FD_ZERO (&fds);
- FD_ZERO (&fds1);
- for(retval= -1; retval < 0;) {
- selecttimeout.tv_sec = connect_timeout;
- selecttimeout.tv_usec = 0;
- FD_SET (tds->s, &fds);
- FD_SET (tds->s, &fds1);
- retval = select(tds->s + 1, NULL, &fds, &fds1,
- (connect_timeout > 0)? &selecttimeout : NULL);
- if((retval < 0) && (errno != EINTR)) {
- break;
- }
- }
- if(retval > 0) {
- int r, r_len= sizeof(r);
- if(FD_ISSET(tds->s, &fds1)) retval= -1;
- if(getsockopt(tds->s, SOL_SOCKET, SO_ERROR, &r, &r_len) < 0 ||
- r != 0) retval= -1;
- }
- if(retval > 0)
- break;
- close(tds->s);
- tds->s= 0;
- }
- if(n >= NCBI_NUM_SERVERS) {
- tds_client_msg(tds->tds_ctx, tds, 20009, 9, 0, 0,
- "Server is unavailable or does not exist.");
- tds_free_config(config);
- tds_free_socket(tds);
- return NULL;
- }
- if (IS_TDS7_PLUS(tds)) {
- tds->out_flag=0x10;
- tds7_send_login(tds,config);
- } else {
- tds->out_flag=0x02;
- tds_send_login(tds,config);
- }
- if (!tds_process_login_tokens(tds)) {
- tds_client_msg(tds->tds_ctx, tds, 20014, 9, 0, 0,
- "Login incorrect.");
- tds_free_config(config);
- tds_free_socket(tds);
- tds = NULL;
- return NULL;
- }
- if (tds && config->text_size) {
- sprintf(query,"set textsize %d", config->text_size);
- retval = tds_submit_query(tds,query);
- if (retval == TDS_SUCCEED) {
- while (tds_process_result_tokens(tds)==TDS_SUCCEED);
- }
- }
- tds->config = NULL;
- tds_free_config(config);
- return tds;
- }
- #else
- TDSSOCKET *tds_connect(TDSLOGIN *login, TDSCONTEXT *context, void *parent)
- {
- TDSSOCKET *tds;
- struct sockaddr_in sin;
- /* Jeff's hack - begin */
- unsigned long ioctl_blocking = 1;
- struct timeval selecttimeout;
- fd_set fds;
- int retval;
- time_t start, now;
- TDSCONFIGINFO *config;
- /* 13 + max string of 32bit int, 30 should cover it */
- char query[30];
- char *tmpstr;
- int connect_timeout = 0;
- FD_ZERO (&fds);
- /* end */
- config = tds_get_config(NULL, login, context->locale);
- /*
- ** If a dump file has been specified, start logging
- */
- if (config->dump_file) {
- tdsdump_open(config->dump_file);
- }
- /*
- ** The initial login packet must have a block size of 512.
- ** Once the connection is established the block size can be changed
- ** by the server with TDS_ENV_CHG_TOKEN
- */
- tds = tds_alloc_socket(context, 512);
- tds_set_parent(tds, parent);
- tds->config = config;
- tds->major_version=config->major_version;
- tds->minor_version=config->minor_version;
- tds->emul_little_endian=config->emul_little_endian;
- #ifdef WORDS_BIGENDIAN
- if (IS_TDS70(tds) || IS_TDS80(tds)) {
- /* TDS 7/8 only supports little endian */
- tds->emul_little_endian=1;
- }
- #endif
- /* set up iconv */
- if (config->client_charset) {
- tds_iconv_open(tds, config->client_charset);
- }
- /* specified a date format? */
- /*
- if (config->date_fmt) {
- tds->date_fmt=strdup(config->date_fmt);
- }
- */
- if (login->connect_timeout) {
- connect_timeout = login->connect_timeout;
- } else if (config->connect_timeout) {
- connect_timeout = config->connect_timeout;
- }
- /* Jeff's hack - begin */
- tds->timeout = (connect_timeout) ? login->query_timeout : 0;
- tds->longquery_timeout = (connect_timeout) ? login->longquery_timeout : 0;
- tds->longquery_func = login->longquery_func;
- tds->longquery_param = login->longquery_param;
- /* end */
- /* verify that ip_addr is not NULL */
- if (!config->ip_addr) {
- tdsdump_log(TDS_DBG_ERROR, "%L IP address pointer is NULLn");
- if (config->server_name) {
- tmpstr = malloc(strlen(config->server_name)+100);
- if (tmpstr) {
- sprintf(tmpstr,"Server %s not found!",config->server_name);
- tds_client_msg(tds->tds_ctx, tds, 10019, 9, 0, 0, tmpstr);
- free(tmpstr);
- }
- } else {
- tds_client_msg(tds->tds_ctx, tds, 10020, 9, 0, 0, "No server specified!");
- }
- tds_free_config(config);
- tds_free_socket(tds);
- return NULL;
- }
- sin.sin_addr.s_addr = inet_addr(config->ip_addr);
- if (sin.sin_addr.s_addr == -1) {
- tdsdump_log(TDS_DBG_ERROR, "%L inet_addr() failed, IP = %sn", config->ip_addr);
- tds_free_config(config);
- tds_free_socket(tds);
- return NULL;
- }
- sin.sin_family = AF_INET;
- sin.sin_port = htons(config->port);
- memcpy(tds->capabilities,login->capabilities,TDS_MAX_CAPABILITY);
- tdsdump_log(TDS_DBG_INFO1, "%L Connecting addr %s port %dn", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
- if ((tds->s = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
- perror ("socket");
- tds_free_config(config);
- tds_free_socket(tds);
- return NULL;
- }
- /* Jeff's hack *** START OF NEW CODE *** */
- if (connect_timeout) {
- start = time (NULL);
- ioctl_blocking = 1; /* ~0; //TRUE; */
- if (IOCTL(tds->s, FIONBIO, &ioctl_blocking) < 0) {
- tds_free_config(config);
- tds_free_socket(tds);
- return NULL;
- }
- retval = connect(tds->s, (struct sockaddr *) &sin, sizeof(sin));
- if (retval < 0 && errno == EINPROGRESS) retval = 0;
- if (retval < 0) {
- tds_client_msg(tds->tds_ctx, tds, 20009, 9, 0, 0,
- "Server is unavailable or does not exist.");
- tds_free_config(config);
- tds_free_socket(tds);
- return NULL;
- }
- /* Select on writeability for connect_timeout */
- now = start;
- while ((retval == 0) && ((now-start) < connect_timeout)) {
- FD_SET (tds->s, &fds);
- selecttimeout.tv_sec = connect_timeout - (now-start);
- selecttimeout.tv_usec = 0;
- retval = select(tds->s + 1, NULL, &fds, NULL, &selecttimeout);
- if (retval < 0 && errno == EINTR)
- retval = 0;
- now = time (NULL);
- }
- if ((now-start) > connect_timeout) {
- tds_client_msg(tds->tds_ctx, tds, 20009, 9, 0, 0,
- "Server is unavailable or does not exist.");
- tds_free_config(config);
- tds_free_socket(tds);
- return NULL;
- }
- } else {
- if (connect(tds->s, (struct sockaddr *) &sin, sizeof(sin)) <0) {
- char message[128];
- sprintf(message, "src/tds/login.c: tds_connect: %s:%d",
- inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
- perror(message);
- tds_client_msg(tds->tds_ctx, tds, 20009, 9, 0, 0,
- "Server is unavailable or does not exist.");
- tds_free_config(config);
- tds_free_socket(tds);
- return NULL;
- }
- }
- /* END OF NEW CODE */
- if (IS_TDS7_PLUS(tds)) {
- tds->out_flag=0x10;
- tds7_send_login(tds,config);
- } else {
- tds->out_flag=0x02;
- tds_send_login(tds,config);
- }
- if (!tds_process_login_tokens(tds)) {
- tds_client_msg(tds->tds_ctx, tds, 20014, 9, 0, 0,
- "Login incorrect.");
- tds_free_config(config);
- tds_free_socket(tds);
- tds = NULL;
- return NULL;
- }
- if (tds && config->text_size) {
- sprintf(query,"set textsize %d", config->text_size);
- retval = tds_submit_query(tds,query);
- if (retval == TDS_SUCCEED) {
- while (tds_process_result_tokens(tds)==TDS_SUCCEED);
- }
- }
- tds->config = NULL;
- tds_free_config(config);
- return tds;
- }
- #endif
- int tds_send_login(TDSSOCKET *tds, TDSCONFIGINFO *config)
- {
- /* char *tmpbuf;
- int tmplen;*/
- #ifdef WORDS_BIGENDIAN
- unsigned char be1[]= {0x02,0x00,0x06,0x04,0x08,0x01};
- #endif
- unsigned char le1[]= {0x03,0x01,0x06,0x0a,0x09,0x01};
- unsigned char magic2[]={0x00,0x00};
-
- unsigned char magic3[]= {0x00,0x00,0x00};
-
- /* these seem to endian flags as well 13,17 on intel/alpha 12,16 on power */
-
- #ifdef WORDS_BIGENDIAN
- unsigned char be2[]= {0x00,12,16};
- #endif
- unsigned char le2[]= {0x00,13,17};
-
- /*
- ** the former byte 0 of magic5 causes the language token and message to be
- ** absent from the login acknowledgement if set to 1. There must be a way
- ** of setting this in the client layer, but I am not aware of any thing of
- ** the sort -- bsb 01/17/99
- */
- unsigned char magic5[]= {0x00,0x00};
- unsigned char magic6[]= {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
- unsigned char magic7= 0x01;
-
- unsigned char magic42[]= {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
- unsigned char magic50[]= {0x00,0x00,0x00,0x00};
- /*
- ** capabilities are now part of the tds structure.
- unsigned char capabilities[]= {0x01,0x07,0x03,109,127,0xFF,0xFF,0xFF,0xFE,0x02,0x07,0x00,0x00,0x0A,104,0x00,0x00,0x00};
- */
- /*
- ** This is the original capabilities packet we were working with (sqsh)
- unsigned char capabilities[]= {0x01,0x07,0x03,109,127,0xFF,0xFF,0xFF,0xFE,0x02,0x07,0x00,0x00,0x0A,104,0x00,0x00,0x00};
- ** original with 4.x messages
- unsigned char capabilities[]= {0x01,0x07,0x03,109,127,0xFF,0xFF,0xFF,0xFE,0x02,0x07,0x00,0x00,0x00,120,192,0x00,0x0D};
- ** This is isql 11.0.3
- unsigned char capabilities[]= {0x01,0x07,0x00,96, 129,207, 0xFF,0xFE,62, 0x02,0x07,0x00,0x00,0x00,120,192,0x00,0x0D};
- ** like isql but with 5.0 messages
- unsigned char capabilities[]= {0x01,0x07,0x00,96, 129,207, 0xFF,0xFE,62, 0x02,0x07,0x00,0x00,0x00,120,192,0x00,0x00};
- **
- */
-
- unsigned char protocol_version[4];
- unsigned char program_version[4];
-
- int rc;
- char blockstr[10], passwdstr[255];
-
- if (IS_TDS42(tds)) {
- memcpy(protocol_version,"