NCBI C++ ToolKit
login.c
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Brian Bruns
3  * Copyright (C) 2005-2015 Ziglio Frediano
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20 
21 #include <config.h>
22 
23 #include <stdarg.h>
24 #include <stdio.h>
25 
26 #if HAVE_STDLIB_H
27 #include <stdlib.h>
28 #endif /* HAVE_STDLIB_H */
29 
30 #include <assert.h>
31 
32 #if HAVE_STRING_H
33 #include <string.h>
34 #endif /* HAVE_STRING_H */
35 
36 #if HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif /* HAVE_UNISTD_H */
39 
40 #if HAVE_SYS_SOCKET_H
41 #include <sys/socket.h>
42 #endif /* HAVE_SYS_SOCKET_H */
43 
44 #ifdef _WIN32
45 #include <process.h>
46 #endif
47 
48 #include <freetds/tds.h>
49 #include <freetds/iconv.h>
50 #include <freetds/string.h>
51 #include <freetds/bytes.h>
52 #include <freetds/tls.h>
53 #include <freetds/stream.h>
54 #include <freetds/checks.h>
55 #include "replacements.h"
56 
60 static void tds7_crypt_pass(const unsigned char *clear_pass,
61  size_t len, unsigned char *crypt_pass);
62 
63 #undef MIN
64 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
65 
66 void
68 {
69  tds_login->tds_version = ((TDS_USMALLINT) major_ver << 8) + minor_ver;
70 }
71 
72 void
73 tds_set_packet(TDSLOGIN * tds_login, int packet_size)
74 {
75  tds_login->block_size = packet_size;
76 }
77 
78 void
80 {
81  tds_login->port = port;
82 }
83 
84 bool
85 tds_set_passwd(TDSLOGIN * tds_login, const char *password)
86 {
87  if (password) {
89  return !!tds_dstr_copy(&tds_login->password, password);
90  }
91  return true;
92 }
93 void
95 {
96  tds_login->bulk_copy = enabled ? 1 : 0;
97 }
98 
99 bool
100 tds_set_user(TDSLOGIN * tds_login, const char *username)
101 {
102  return !!tds_dstr_copy(&tds_login->user_name, username);
103 }
104 
105 bool
106 tds_set_host(TDSLOGIN * tds_login, const char *hostname)
107 {
108  return !!tds_dstr_copy(&tds_login->client_host_name, hostname);
109 }
110 
111 bool
112 tds_set_app(TDSLOGIN * tds_login, const char *application)
113 {
114  return !!tds_dstr_copy(&tds_login->app_name, application);
115 }
116 
117 /**
118  * \brief Set the servername in a TDSLOGIN structure
119  *
120  * Normally copies \a server into \a tds_login. If \a server does not point to a plausible name, the environment
121  * variables TDSQUERY and DSQUERY are used, in that order. If they don't exist, the "default default" servername
122  * is "SYBASE" (although the utility of that choice is a bit murky).
123  *
124  * \param tds_login points to a TDSLOGIN structure
125  * \param server the servername, or NULL, or a zero-length string
126  * \todo open the log file earlier, so these messages can be seen.
127  */
128 bool
129 tds_set_server(TDSLOGIN * tds_login, const char *server)
130 {
131 #if 0
132  /* Doing this in tds_alloc_login instead */
133  static const char *names[] = { "TDSQUERY", "DSQUERY", "SYBASE" };
134  int i;
135 
136  for (i=0; i < TDS_VECTOR_SIZE(names) && (!server || strlen(server) == 0); i++) {
137  const char *source;
138  if (i + 1 == TDS_VECTOR_SIZE(names)) {
139  server = names[i];
140  source = "compiled-in default";
141  } else {
142  server = getenv(names[i]);
143  source = names[i];
144  }
145  if (server) {
146  tdsdump_log(TDS_DBG_INFO1, "Setting TDSLOGIN::server_name to '%s' from %s.\n", server, source);
147  }
148  }
149 #endif
150  if (server)
151  return !!tds_dstr_copy(&tds_login->server_name, server);
152  return true;
153 }
154 
155 bool
156 tds_set_library(TDSLOGIN * tds_login, const char *library)
157 {
158  return !!tds_dstr_copy(&tds_login->library, library);
159 }
160 
161 bool
163 {
164  return !!tds_dstr_copy(&tds_login->client_charset, charset);
165 }
166 
167 bool
168 tds_set_language(TDSLOGIN * tds_login, const char *language)
169 {
170  return !!tds_dstr_copy(&tds_login->language, language);
171 }
172 
174 {
176  char type;
177 };
178 
180 {
181  char *oldval;
182  char *newval;
183  int type;
184 };
185 
186 typedef struct tds_save_context
187 {
188  /* must be first !!! */
190 
191  unsigned num_msg;
192  struct tds_save_msg msgs[10];
193 
194  unsigned num_env;
195  struct tds_save_env envs[10];
197 
198 static void
200 {
201  struct tds_save_msg *dest_msg;
202 
203  if (ctx->num_msg >= TDS_VECTOR_SIZE(ctx->msgs))
204  return;
205 
206  dest_msg = &ctx->msgs[ctx->num_msg];
207  dest_msg->type = type;
208  dest_msg->msg = *msg;
209  dest_msg->msg.osstr = NULL;
210 #define COPY(name) if (msg->name) dest_msg->msg.name = strdup(msg->name);
211  COPY(server);
212  COPY(message);
213  COPY(proc_name);
214  COPY(sql_state);
215 #undef COPY
216  ++ctx->num_msg;
217 }
218 
219 static int
221 {
222  tds_save((TDSSAVECONTEXT *) ctx, 0, msg);
223  return 0;
224 }
225 
226 static int
228 {
229  tds_save((TDSSAVECONTEXT *) ctx, 1, msg);
230  return TDS_INT_CANCEL;
231 }
232 
233 static void
234 tds_save_env(TDSSOCKET * tds, int type, char *oldval, char *newval)
235 {
237  struct tds_save_env *env;
238 
240  return;
241 
243  if (ctx->num_env >= TDS_VECTOR_SIZE(ctx->envs))
244  return;
245 
246  env = &ctx->envs[ctx->num_env];
247  env->type = type;
248  env->oldval = oldval ? strdup(oldval) : NULL;
249  env->newval = newval ? strdup(newval) : NULL;
250  ++ctx->num_env;
251 }
252 
253 static void
255 {
256  memset(ctx, 0, sizeof(*ctx));
257  ctx->ctx.locale = old_ctx->locale;
258  ctx->ctx.msg_handler = tds_save_msg;
259  ctx->ctx.err_handler = tds_save_err;
260 }
261 
262 static void
264 {
265  unsigned n;
266 
267  /* replay all recorded messages */
268  for (n = 0; n < ctx->num_msg; ++n)
269  if (ctx->msgs[n].type == 0) {
271  tds_get_ctx(tds)->msg_handler(tds_get_ctx(tds), tds, &ctx->msgs[n].msg);
272  } else {
274  tds_get_ctx(tds)->err_handler(tds_get_ctx(tds), tds, &ctx->msgs[n].msg);
275  }
276 
277  /* replay all recorded envs */
278  for (n = 0; n < ctx->num_env; ++n)
279  if (tds->env_chg_func)
280  tds->env_chg_func(tds, ctx->envs[n].type, ctx->envs[n].oldval, ctx->envs[n].newval);
281 }
282 
283 static void
285 {
286  unsigned n;
287 
288  /* free all messages */
289  for (n = 0; n < ctx->num_msg; ++n)
290  tds_free_msg(&ctx->msgs[n].msg);
291  ctx->num_msg = 0;
292 
293  /* free all envs */
294  for (n = 0; n < ctx->num_env; ++n) {
295  free(ctx->envs[n].oldval);
296  free(ctx->envs[n].newval);
297  }
298  ctx->num_env = 0;
299 }
300 
301 static void
303 {
305 }
306 
307 /**
308  * Retrieve and set @@spid
309  * \tds
310  */
311 static TDSRET
313 {
314  TDS_INT result_type;
315  TDS_INT done_flags;
316  TDSRET rc;
317  TDSCOLUMN *curcol;
318 
320 
321  while ((rc = tds_process_tokens(tds, &result_type, &done_flags, TDS_RETURN_ROW|TDS_RETURN_DONE)) == TDS_SUCCESS) {
322 
323  switch (result_type) {
324  case TDS_ROW_RESULT:
325  if (!tds->res_info)
326  return TDS_FAIL;
327  if (tds->res_info->num_cols != 1)
328  break;
329  curcol = tds->res_info->columns[0];
330  switch (tds_get_conversion_type(curcol->column_type, curcol->column_size)) {
331  case SYBINT2:
332  tds->conn->spid = *((TDS_USMALLINT *) curcol->column_data);
333  break;
334  case SYBINT4:
335  tds->conn->spid = *((TDS_UINT *) curcol->column_data);
336  break;
337  default:
338  return TDS_FAIL;
339  }
340  break;
341 
342  case TDS_DONE_RESULT:
343  if ((done_flags & TDS_DONE_ERROR) != 0)
344  return TDS_FAIL;
345  break;
346  }
347  }
348  if (rc == TDS_NO_MORE_RESULTS)
349  rc = TDS_SUCCESS;
350 
351  return rc;
352 }
353 
354 /**
355  * Do a connection to socket
356  * @param tds connection structure. This should be a non-connected connection.
357  * @return TDS_FAIL or TDS_SUCCESS if a connection was made to the server's port.
358  * @return TDSERROR enumerated type if no TCP/IP connection could be formed.
359  * @param login info for login
360  * @remark Possible error conditions:
361  * - TDSESOCK: socket(2) failed: insufficient local resources
362  * - TDSECONN: connect(2) failed: invalid hostname or port (ETIMEDOUT, ECONNREFUSED, ENETUNREACH)
363  * - TDSEFCON: connect(2) succeeded, login packet not acknowledged.
364  * - TDS_FAIL: connect(2) succeeded, login failed.
365  */
366 static int
368 {
369  int erc = -TDSEFCON;
370  int connect_timeout = 0;
371  int db_selected = 0;
372  struct addrinfo *addrs;
373  int orig_port;
374  bool rerouted = false;
375 
376  /*
377  * A major version of 0 means try to guess the TDS version.
378  * We try them in an order that should work.
379  */
380  const static TDS_USMALLINT versions[] =
381  { /* 0x703, 0x702, */
382  0x701
383  , 0x700
384  , 0x500
385  , 0x402
386  };
387 
388  if (!login->valid_configuration) {
390  return TDS_FAIL;
391  }
392 
393  if (TDS_MAJOR(login) == 0) {
394  unsigned int i;
395  TDSSAVECONTEXT save_ctx;
396  const TDSCONTEXT *old_ctx = tds_get_ctx(tds);
397  typedef void (*env_chg_func_t) (TDSSOCKET * tds, int type, char *oldval, char *newval);
398  env_chg_func_t old_env_chg = tds->env_chg_func;
399 #if 0
400  /* the context of a socket is const; we have to modify it to suppress error messages during multiple tries. */
401  TDSCONTEXT *mod_ctx = (TDSCONTEXT *) tds_get_ctx(tds);
402  err_handler_t err_handler = tds_get_ctx(tds)->err_handler;
403 #endif
404 
405  init_save_context(&save_ctx, old_ctx);
406  tds_set_ctx(tds, &save_ctx.ctx);
408 #if 0
409  mod_ctx->err_handler = NULL;
410 #endif
411 
412  for (i = 0; i < TDS_VECTOR_SIZE(versions); ++i) {
413  int orig_size = tds->conn->env.block_size;
414  login->tds_version = versions[i];
415  reset_save_context(&save_ctx);
416 
417  erc = tds_connect(tds, login, p_oserr);
418  if (TDS_FAILED(erc)) {
420  if (tds->conn->env.block_size != orig_size) {
421  tds_realloc_socket(tds, orig_size);
422  }
423  }
424 
425  if (erc != -TDSEFCON) /* TDSEFCON indicates wrong TDS version */
426  break;
427  }
428 
429 #if 0
430  mod_ctx->err_handler = err_handler;
431 #endif
432  tds->env_chg_func = old_env_chg;
433  tds_set_ctx(tds, old_ctx);
434  replay_save_context(tds, &save_ctx);
435  free_save_context(&save_ctx);
436 
437  if (TDS_FAILED(erc))
438  tdserror(tds_get_ctx(tds), tds, -erc, *p_oserr);
439 
440  return erc;
441  }
442 
443 
444  /*
445  * If a dump file has been specified, start logging
446  */
448  if (login->debug_flags)
451  }
452 
453  tds->login = login;
454 
457 #ifdef WORDS_BIGENDIAN
458  /*
459  * Enable automatically little endian emulation.
460  * TDS 7/8 only supports little endian.
461  * This is done even for 4.2 to ensure that when we connect to a
462  * MSSQL we use it and avoid to make additional checks for
463  * broken 7.0 servers.
464  * Note that 4.2 should not be used anymore for real jobs.
465  */
466  if (IS_TDS7_PLUS(tds->conn) || IS_TDS42(tds->conn))
468 #endif
469 
470  /* set up iconv if not already initialized*/
471  if (tds->conn->char_convs[client2ucs2]->to.cd == (iconv_t) -1) {
474  return -TDSEMEM;
475  }
476  }
477 
478  connect_timeout = login->connect_timeout;
479 
480  /* Jeff's hack - begin */
481  tds->query_timeout = connect_timeout ? connect_timeout : login->query_timeout;
482  /* end */
483 
484  /* verify that ip_addr is not empty */
485  if (login->ip_addrs == NULL) {
487  tdsdump_log(TDS_DBG_ERROR, "IP address pointer is empty\n");
489  tdsdump_log(TDS_DBG_ERROR, "Server %s not found!\n", tds_dstr_cstr(&login->server_name));
490  } else {
491  tdsdump_log(TDS_DBG_ERROR, "No server specified!\n");
492  }
493  return -TDSECONN;
494  }
495 
497 
498 reroute:
499  erc = TDSEINTF;
500  orig_port = login->port;
501  for (addrs = login->ip_addrs; addrs != NULL; addrs = addrs->ai_next) {
502 
503  /*
504  * By some reasons ftds forms 3 linked tds_addrinfo (addrs
505  * variable here) for one server address. The structures
506  * differs in their ai_socktype and ai_protocol field
507  * values. Typically the combinations are:
508  * ai_socktype | ai_protocol
509  * -----------------------------
510  * 1 (SOCK_STREAM) | 6 (tcp)
511  * 2 (SOCK_DGRAM) | 17 (udp)
512  * 3 (SOCK_RAW) | 0 (ip)
513  *
514  * Later on these fields are not used and dtds always
515  * creates a tcp socket. In case if there is a connection
516  * problem this behavior leads to 3 tries with the provided
517  * timeout which basically multiplies the spent time
518  * without any good result. So it was decided to skip the
519  * non tcp addresses.
520  *
521  * NOTE: on Windows exactly one tds_addrinfo structure is
522  * formed and it has 0 in both ai_socktype and
523  * ai_protocol fields. So skipping is conditional for
524  * non-Windows platforms
525  */
526 #ifndef _WIN32
527  if (addrs->ai_socktype != SOCK_STREAM)
528  continue;
529 #endif
530 
531  login->port = orig_port;
532 
535 
536  if (login->port >= 1) {
537  if ((erc = tds_open_socket(tds, addrs, login->port, connect_timeout, p_oserr)) == TDSEOK) {
538  login->connected_addr = addrs;
539  break;
540  }
541  } else {
542  erc = TDSECONN;
543  }
544  }
545 
546  if (erc != TDSEOK) {
547  if (login->port < 1)
548  tdsdump_log(TDS_DBG_ERROR, "invalid port number\n");
549 
550  tdserror(tds_get_ctx(tds), tds, erc, *p_oserr);
551  return -erc;
552  }
553 
554  /*
555  * Beyond this point, we're connected to the server. We know we have a valid TCP/IP address+socket pair.
556  * Although network errors *might* happen, most problems from here on out will be TDS-level errors,
557  * either TDS version problems or authentication problems.
558  */
559 
561  tds->conn->spid = -1;
562 
563  /* discard possible previous authentication */
564  if (tds->conn->authentication) {
567  }
568 
569  if (IS_TDS71_PLUS(tds->conn)) {
570  erc = tds71_do_login(tds, login);
571  db_selected = 1;
572  } else if (IS_TDS7_PLUS(tds->conn)) {
573  erc = tds7_send_login(tds, login);
574  db_selected = 1;
575  } else {
577  erc = tds_send_login(tds, login);
578  }
580  tdsdump_log(TDS_DBG_ERROR, "login packet %s\n", TDS_SUCCEED(erc)? "accepted":"rejected");
582  tdserror(tds_get_ctx(tds), tds, TDSEFCON, 0); /* "Adaptive Server connection failed" */
583  return -TDSEFCON;
584  }
585 
586  /* need to do rerouting */
587  if (IS_TDS71_PLUS(tds->conn) && !rerouted
589  TDSRET ret;
590 
594  login->routing_port = 0;
596  if (TDS_FAILED(ret)) {
598  return -TDSEFCON;
599  }
600  rerouted = true;
601  goto reroute;
602  }
603 
604 #if ENABLE_ODBC_MARS
605  /* initialize SID */
606  if (IS_TDS72_PLUS(tds->conn) && login->mars) {
607  tds->conn->sessions[0] = NULL;
608  tds->conn->mars = 1;
609  tds->sid = -1;
611  }
612 #endif
613 
614  if (login->text_size || (!db_selected && !tds_dstr_isempty(&login->database))
615  || tds->conn->spid == -1) {
616  char *str;
617  size_t len;
618 
620  if ((str = tds_new(char, len)) == NULL)
621  return TDS_FAIL;
622 
623  str[0] = 0;
624  if (login->text_size) {
625  sprintf(str, "set textsize %d ", login->text_size);
626  }
627  if (tds->conn->spid == -1) {
628  strcat(str, "select @@spid ");
629  }
630  /* Select proper database if specified.
631  * SQL Anywhere does not support multiple databases and USE statement
632  * so don't send the request to avoid connection failures */
633  if (!db_selected && !tds_dstr_isempty(&login->database) &&
634  (tds->conn->product_name == NULL || strcasecmp(tds->conn->product_name, "SQL Anywhere") != 0)) {
635  strcat(str, "use ");
636  tds_quote_id(tds, strchr(str, 0), tds_dstr_cstr(&login->database), -1);
637  }
638  erc = tds_submit_query(tds, str);
639  free(str);
640  if (TDS_FAILED(erc))
641  return erc;
642 
643  if (tds->conn->spid == -1)
644  erc = tds_set_spid(tds);
645  else
647  if (TDS_FAILED(erc))
648  return erc;
649  }
650 
652  tds->login = NULL;
653  return TDS_SUCCESS;
654 }
655 
656 int
658 {
659  int oserr = 0;
660  return tds_connect(tds, login, &oserr);
661 }
662 
663 static int
664 tds_put_login_string(TDSSOCKET * tds, const char *buf, int n)
665 {
666  const int buf_len = buf ? (int)strlen(buf) : 0;
667  return tds_put_buf(tds, (const unsigned char *) buf, n, buf_len);
668 }
669 
670 static TDSRET
672 {
673 #ifdef WORDS_BIGENDIAN
674  static const unsigned char be1[] = { 0x02, 0x00, 0x06, 0x04, 0x08, 0x01 };
675  static const unsigned char be2[] = { 0x00, 12, 16 };
676 #endif
677  static const unsigned char le1[] = { 0x03, 0x01, 0x06, 0x0a, 0x09, 0x01 };
678  static const unsigned char le2[] = { 0x00, 13, 17 };
679 
680  /*
681  * capabilities are now part of the tds structure.
682  * unsigned char capabilities[]= {0x01,0x07,0x03,109,127,0xFF,0xFF,0xFF,0xFE,0x02,0x07,0x00,0x00,0x0A,104,0x00,0x00,0x00};
683  */
684  /*
685  * This is the original capabilities packet we were working with (sqsh)
686  * unsigned char capabilities[]= {0x01,0x07,0x03,109,127,0xFF,0xFF,0xFF,0xFE,0x02,0x07,0x00,0x00,0x0A,104,0x00,0x00,0x00};
687  * original with 4.x messages
688  * unsigned char capabilities[]= {0x01,0x07,0x03,109,127,0xFF,0xFF,0xFF,0xFE,0x02,0x07,0x00,0x00,0x00,120,192,0x00,0x0D};
689  * This is isql 11.0.3
690  * unsigned char capabilities[]= {0x01,0x07,0x00,96, 129,207, 0xFF,0xFE,62, 0x02,0x07,0x00,0x00,0x00,120,192,0x00,0x0D};
691  * like isql but with 5.0 messages
692  * unsigned char capabilities[]= {0x01,0x07,0x00,96, 129,207, 0xFF,0xFE,62, 0x02,0x07,0x00,0x00,0x00,120,192,0x00,0x00};
693  */
694 
695  unsigned char protocol_version[4];
696  unsigned char program_version[4];
697 
698  int len;
699  char blockstr[16];
700 
701  /* override lservname field for ASA servers */
702  const char *lservname = getenv("ASA_DATABASE")? getenv("ASA_DATABASE") : tds_dstr_cstr(&login->server_name);
703 
704  if (strchr(tds_dstr_cstr(&login->user_name), '\\') != NULL) {
705  tdsdump_log(TDS_DBG_ERROR, "NT login not support using TDS 4.x or 5.0\n");
706  return TDS_FAIL;
707  }
709  tdsdump_log(TDS_DBG_ERROR, "Kerberos login not support using TDS 4.x or 5.0\n");
710  return TDS_FAIL;
711  }
713  if (IS_TDS42(tds->conn)) {
714  tdsdump_log(TDS_DBG_ERROR, "Encryption not support using TDS 4.x\n");
715  return TDS_FAIL;
716  }
718  if (!tds->conn->authentication)
719  return TDS_FAIL;
720  }
721 
722  if (IS_TDS42(tds->conn)) {
723  memcpy(protocol_version, "\004\002\000\000", 4);
724  memcpy(program_version, "\004\002\000\000", 4);
725  } else if (IS_TDS46(tds->conn)) {
726  memcpy(protocol_version, "\004\006\000\000", 4);
727  memcpy(program_version, "\004\002\000\000", 4);
728  } else if (IS_TDS50(tds->conn)) {
729  memcpy(protocol_version, "\005\000\000\000", 4);
730  memcpy(program_version, "\005\000\000\000", 4);
731  } else {
732  tdsdump_log(TDS_DBG_SEVERE, "Unknown protocol version!\n");
733  return TDS_FAIL;
734  }
735  /*
736  * the following code is adapted from Arno Pedusaar's
737  * (psaar@fenar.ee) MS-SQL Client. His was a much better way to
738  * do this, (well...mine was a kludge actually) so here's mostly his
739  */
740 
743  /* account password */
746  } else {
748  }
749  sprintf(blockstr, "%d", (int) getpid());
750  tds_put_login_string(tds, blockstr, TDS_MAXNAME); /* host process */
751 #ifdef WORDS_BIGENDIAN
752  if (tds->conn->emul_little_endian) {
753  tds_put_n(tds, le1, 6);
754  } else {
755  tds_put_n(tds, be1, 6);
756  }
757 #else
758  tds_put_n(tds, le1, 6);
759 #endif
761  tds_put_n(tds, NULL, 2);
762  if (IS_TDS42(tds->conn)) {
763  tds_put_int(tds, 512);
764  } else {
765  tds_put_int(tds, 0);
766  }
767  tds_put_n(tds, NULL, 3);
769  tds_put_login_string(tds, lservname, TDS_MAXNAME);
770  if (IS_TDS42(tds->conn)) {
772  } else if (login->encryption_level) {
773  tds_put_n(tds, NULL, 256);
774  } else {
776  if (len > 253)
777  len = 0;
778  tds_put_byte(tds, 0);
779  tds_put_byte(tds, len);
781  tds_put_n(tds, NULL, 253 - len);
782  tds_put_byte(tds, len + 2);
783  }
784 
785  tds_put_n(tds, protocol_version, 4); /* TDS version; { 0x04,0x02,0x00,0x00 } */
786  tds_put_login_string(tds, tds_dstr_cstr(&login->library), TDS_PROGNLEN); /* client program name */
787  if (IS_TDS42(tds->conn)) {
788  tds_put_int(tds, 0);
789  } else {
790  tds_put_n(tds, program_version, 4); /* program version ? */
791  }
792 #ifdef WORDS_BIGENDIAN
793  if (tds->conn->emul_little_endian) {
794  tds_put_n(tds, le2, 3);
795  } else {
796  tds_put_n(tds, be2, 3);
797  }
798 #else
799  tds_put_n(tds, le2, 3);
800 #endif
803 
804  /* oldsecure(2), should be zero, used by old software */
805  tds_put_n(tds, NULL, 2);
806  /* seclogin(1) bitmask */
808  /* secbulk(1)
809  * halogin(1) type of ha login
810  * hasessionid(6) id of session to reconnect
811  * secspare(2) not used
812  */
813  tds_put_n(tds, NULL, 10);
814 
815  /* use empty charset to handle conversions on client */
816  tds_put_login_string(tds, "", TDS_MAXNAME); /* charset */
817  /* this is a flag, mean that server should use character set provided by client */
818  /* TODO notify charset change ?? what's correct meaning ?? -- freddy77 */
819  tds_put_byte(tds, 1);
820 
821  /* network packet size */
822  if (login->block_size < 65536u && login->block_size >= 512)
823  sprintf(blockstr, "%d", login->block_size);
824  else
825  strcpy(blockstr, "512");
826  tds_put_login_string(tds, blockstr, TDS_PKTLEN);
827 
828  if (IS_TDS42(tds->conn)) {
829  tds_put_n(tds, NULL, 8);
830  } else if (IS_TDS46(tds->conn)) {
831  tds_put_n(tds, NULL, 4);
832  } else if (IS_TDS50(tds->conn)) {
833  /* just padding to 8 bytes */
834  tds_put_n(tds, NULL, 4);
838  }
839 
840  return tds_flush_packet(tds);
841 }
842 
843 /**
844  * tds7_send_login() -- Send a TDS 7.0 login packet
845  * TDS 7.0 login packet is vastly different and so gets its own function
846  * \returns the return value is ignored by the caller. :-/
847  */
848 static TDSRET
850 {
851  static const unsigned char
852  client_progver[] = { 6, 0x83, 0xf2, 0xf8 },
853 
854  connection_id[] = { 0x00, 0x00, 0x00, 0x00 },
855  collation[] = { 0x36, 0x04, 0x00, 0x00 };
856 
857  enum {
858  tds70Version = 0x70000000,
859  tds71Version = 0x71000001,
860  tds72Version = 0x72090002,
861  tds73Version = 0x730B0003,
862  tds74Version = 0x74000004,
863  };
864  TDS_UCHAR sql_type_flag = 0x00;
865  TDS_INT time_zone = -120;
866  TDS_INT tds7version = tds70Version;
867 
868  unsigned int block_size = 4096;
869 
870  unsigned char option_flag1 = TDS_SET_LANG_ON | TDS_USE_DB_NOTIFY | TDS_INIT_DB_FATAL;
871  unsigned char option_flag2 = login->option_flag2;
872  unsigned char option_flag3 = 0;
873 
874  unsigned char hwaddr[6];
875  size_t packet_size, current_pos;
876  TDSRET rc;
877 
878  void *data = NULL;
879  TDSDYNAMICSTREAM data_stream;
881 
882  const char *user_name = tds_dstr_cstr(&login->user_name);
883  unsigned char *pwd;
884 
885  /* FIXME: These are defined as size_t, but should be TDS_SMALLINT. */
886  size_t user_name_len = strlen(user_name);
887  size_t auth_len = 0;
888 
889  /* fields */
890  enum {
891  HOST_NAME,
892  USER_NAME,
893  PASSWORD,
894  APP_NAME,
895  SERVER_NAME,
896  LIBRARY_NAME,
897  LANGUAGE,
898  DATABASE_NAME,
899  DB_FILENAME,
900  NEW_PASSWORD,
901  NUM_DATA_FIELDS
902  };
903  struct {
904  const void *ptr;
905  size_t pos, len;
906  } data_fields[NUM_DATA_FIELDS], *field;
907 
909 
910  current_pos = packet_size = IS_TDS72_PLUS(tds->conn) ? 86 + 8 : 86; /* ? */
911 
912  /* check ntlm */
913 #ifdef HAVE_SSPI
914  if (strchr(user_name, '\\') != NULL || user_name_len == 0) {
915  tdsdump_log(TDS_DBG_INFO2, "using SSPI authentication for '%s' account\n", user_name);
916  tds->conn->authentication = tds_sspi_get_auth(tds);
917  if (!tds->conn->authentication)
918  return TDS_FAIL;
919  auth_len = tds->conn->authentication->packet_len;
920  packet_size += auth_len;
921 #else
922  if (strchr(user_name, '\\') != NULL) {
923  tdsdump_log(TDS_DBG_INFO2, "using NTLM authentication for '%s' account\n", user_name);
925  if (!tds->conn->authentication)
926  return TDS_FAIL;
927  auth_len = tds->conn->authentication->packet_len;
928  packet_size += auth_len;
929  } else if (user_name_len == 0) {
930 # ifdef ENABLE_KRB5
931  /* try kerberos */
932  tdsdump_log(TDS_DBG_INFO2, "using GSS authentication\n");
934  if (!tds->conn->authentication)
935  return TDS_FAIL;
936  auth_len = tds->conn->authentication->packet_len;
937  packet_size += auth_len;
938 # else
939  tdsdump_log(TDS_DBG_ERROR, "requested GSS authentication but not compiled in\n");
940  return TDS_FAIL;
941 # endif
942 #endif
943  }
944 
945 
946  /* initialize ouput buffer for strings */
947  rc = tds_dynamic_stream_init(&data_stream, &data, 0);
948  if (TDS_FAILED(rc))
949  return rc;
950 
951 #define SET_FIELD_DSTR(field, dstr) do { \
952  data_fields[field].ptr = tds_dstr_cstr(&(dstr)); \
953  data_fields[field].len = MIN(tds_dstr_len(&(dstr)), 128); \
954  } while(0)
955 
956  /* setup data fields */
958  if (tds->conn->authentication) {
959  data_fields[USER_NAME].len = 0;
960  data_fields[PASSWORD].len = 0;
961  } else {
962  SET_FIELD_DSTR(USER_NAME, login->user_name);
964  }
965  SET_FIELD_DSTR(APP_NAME, login->app_name);
966  SET_FIELD_DSTR(SERVER_NAME, login->server_name);
967  SET_FIELD_DSTR(LIBRARY_NAME, login->library);
968  SET_FIELD_DSTR(LANGUAGE, login->language);
969  SET_FIELD_DSTR(DATABASE_NAME, login->database);
970  SET_FIELD_DSTR(DB_FILENAME, login->db_filename);
971  data_fields[NEW_PASSWORD].len = 0;
973  option_flag3 |= TDS_CHANGE_PASSWORD;
974  SET_FIELD_DSTR(NEW_PASSWORD, login->new_password);
975  }
976 
977  /* convert data fields */
978  for (field = data_fields; field < data_fields + TDS_VECTOR_SIZE(data_fields); ++field) {
979  size_t data_pos;
980 
981  data_pos = data_stream.size;
982  field->pos = current_pos + data_pos;
983  if (field->len) {
984  tds_staticin_stream_init(&input, field->ptr, field->len);
985  rc = tds_convert_stream(tds, tds->conn->char_convs[client2ucs2], to_server, &input.stream, &data_stream.stream);
986  if (TDS_FAILED(rc)) {
987  free(data);
988  return TDS_FAIL;
989  }
990  }
991  field->len = data_stream.size - data_pos;
992  }
993  pwd = (unsigned char *) data + data_fields[PASSWORD].pos - current_pos;
994  tds7_crypt_pass(pwd, data_fields[PASSWORD].len, pwd);
995  pwd = (unsigned char *) data + data_fields[NEW_PASSWORD].pos - current_pos;
996  tds7_crypt_pass(pwd, data_fields[NEW_PASSWORD].len, pwd);
997  packet_size += data_stream.size;
998 
999 #if !defined(TDS_DEBUG_LOGIN)
1000  tdsdump_log(TDS_DBG_INFO2, "quietly sending TDS 7+ login packet\n");
1001  tdsdump_elided = 1;
1002 #endif
1003  TDS_PUT_INT(tds, packet_size);
1004  switch (login->tds_version) {
1005  case 0x700:
1006  tds7version = tds70Version;
1007  break;
1008  case 0x701:
1009  tds7version = tds71Version;
1010  break;
1011  case 0x702:
1012  tds7version = tds72Version;
1013  break;
1014  case 0x703:
1015  tds7version = tds73Version;
1016  break;
1017  case 0x704:
1018  tds7version = tds74Version;
1019  break;
1020  default:
1021  assert(0 && 0x700 <= login->tds_version && login->tds_version <= 0x704);
1022  }
1023 
1024  tds_put_int(tds, tds7version);
1025 
1026  if (4096 <= login->block_size && login->block_size < 65536u)
1027  block_size = login->block_size;
1028 
1029  tds_put_int(tds, block_size); /* desired packet size being requested by client */
1030 
1031  if (block_size > tds->out_buf_max)
1032  tds_realloc_socket(tds, block_size);
1033 
1034  tds_put_n(tds, client_progver, sizeof(client_progver)); /* client program version ? */
1035 
1036  tds_put_int(tds, getpid()); /* process id of this process */
1037 
1038  tds_put_n(tds, connection_id, sizeof(connection_id));
1039 
1040  if (!login->bulk_copy)
1041  option_flag1 |= TDS_DUMPLOAD_OFF;
1042 
1043  tds_put_byte(tds, option_flag1);
1044 
1045  if (tds->conn->authentication)
1046  option_flag2 |= TDS_INTEGRATED_SECURITY_ON;
1047 
1048  tds_put_byte(tds, option_flag2);
1049 
1051  sql_type_flag |= TDS_READONLY_INTENT;
1052  tds_put_byte(tds, sql_type_flag);
1053 
1054  if (IS_TDS73_PLUS(tds->conn))
1055  option_flag3 |= TDS_UNKNOWN_COLLATION_HANDLING;
1056  tds_put_byte(tds, option_flag3);
1057 
1058  tds_put_int(tds, time_zone);
1059  tds_put_n(tds, collation, sizeof(collation));
1060 
1061 #define PUT_STRING_FIELD_PTR(field) do { \
1062  TDS_PUT_SMALLINT(tds, data_fields[field].pos); \
1063  TDS_PUT_SMALLINT(tds, data_fields[field].len / 2u); \
1064  } while(0)
1065 
1066  /* host name */
1067  PUT_STRING_FIELD_PTR(HOST_NAME);
1068  if (tds->conn->authentication) {
1069  tds_put_smallint(tds, 0);
1070  tds_put_smallint(tds, 0);
1071  tds_put_smallint(tds, 0);
1072  tds_put_smallint(tds, 0);
1073  } else {
1074  /* username */
1075  PUT_STRING_FIELD_PTR(USER_NAME);
1076  /* password */
1078  }
1079  /* app name */
1080  PUT_STRING_FIELD_PTR(APP_NAME);
1081  /* server name */
1082  PUT_STRING_FIELD_PTR(SERVER_NAME);
1083  /* unknown */
1084  tds_put_smallint(tds, 0);
1085  tds_put_smallint(tds, 0);
1086  /* library name */
1087  PUT_STRING_FIELD_PTR(LIBRARY_NAME);
1088  /* language - kostya@warmcat.excom.spb.su */
1089  PUT_STRING_FIELD_PTR(LANGUAGE);
1090  /* database name */
1091  PUT_STRING_FIELD_PTR(DATABASE_NAME);
1092 
1093  /* MAC address */
1094  tds_getmac(tds_get_s(tds), hwaddr);
1095  tds_put_n(tds, hwaddr, 6);
1096 
1097  /* authentication stuff */
1098  TDS_PUT_SMALLINT(tds, current_pos + data_stream.size);
1099  TDS_PUT_SMALLINT(tds, auth_len); /* this matches numbers at end of packet */
1100 
1101  /* db file */
1102  PUT_STRING_FIELD_PTR(DB_FILENAME);
1103 
1104  if (IS_TDS72_PLUS(tds->conn)) {
1105  /* new password */
1106  PUT_STRING_FIELD_PTR(NEW_PASSWORD);
1107 
1108  /* SSPI long */
1109  tds_put_int(tds, 0);
1110  }
1111 
1112  tds_put_n(tds, data, data_stream.size);
1113 
1114  if (tds->conn->authentication)
1115  tds_put_n(tds, tds->conn->authentication->packet, auth_len);
1116 
1117  rc = tds_flush_packet(tds);
1118  tdsdump_elided = 0;
1119 
1120  free(data);
1121  return rc;
1122 }
1123 
1124 /**
1125  * tds7_crypt_pass() -- 'encrypt' TDS 7.0 style passwords.
1126  * the calling function is responsible for ensuring crypt_pass is at least
1127  * 'len' characters
1128  */
1129 static void
1130 tds7_crypt_pass(const unsigned char *clear_pass, size_t len, unsigned char *crypt_pass)
1131 {
1132  size_t i;
1133 
1134  for (i = 0; i < len; i++)
1135  crypt_pass[i] = ((clear_pass[i] << 4) | (clear_pass[i] >> 4)) ^ 0xA5;
1136 }
1137 
1138 static TDSRET
1140 {
1141  int i, pkt_len;
1142  const char *instance_name = tds_dstr_isempty(&login->instance_name) ? "MSSQLServer" : tds_dstr_cstr(&login->instance_name);
1143  TDS_USMALLINT instance_name_len = strlen(instance_name) + 1;
1144  TDS_CHAR crypt_flag;
1145  unsigned int start_pos = 21;
1146  TDSRET ret;
1147 
1148 #define START_POS 21
1149 #define UI16BE(n) ((n) >> 8), ((n) & 0xffu)
1150 #define SET_UI16BE(i,n) TDS_PUT_UA2BE(&buf[i],n)
1151  TDS_UCHAR buf[] = {
1152  /* netlib version */
1153  0, UI16BE(START_POS), UI16BE(6),
1154  /* encryption */
1155  1, UI16BE(START_POS + 6), UI16BE(1),
1156  /* instance */
1157  2, UI16BE(START_POS + 6 + 1), UI16BE(0),
1158  /* process id */
1159  3, UI16BE(0), UI16BE(4),
1160  /* MARS enables */
1161  4, UI16BE(0), UI16BE(1),
1162  /* end */
1163  0xff
1164  };
1165  static const TDS_UCHAR netlib8[] = { 8, 0, 1, 0x55, 0, 0 };
1166  static const TDS_UCHAR netlib9[] = { 9, 0, 0, 0, 0, 0 };
1167 
1168  TDS_UCHAR *p;
1169 
1170  SET_UI16BE(13, instance_name_len);
1171  if (!IS_TDS72_PLUS(tds->conn)) {
1172  SET_UI16BE(16, START_POS + 6 + 1 + instance_name_len);
1173  buf[20] = 0xff;
1174  } else {
1175  start_pos += 5;
1176 #undef START_POS
1177 #define START_POS 26
1178  SET_UI16BE(1, START_POS);
1179  SET_UI16BE(6, START_POS + 6);
1180  SET_UI16BE(11, START_POS + 6 + 1);
1181  SET_UI16BE(16, START_POS + 6 + 1 + instance_name_len);
1182  SET_UI16BE(21, START_POS + 6 + 1 + instance_name_len + 4);
1183  }
1184 
1185  assert(start_pos >= 21 && start_pos <= sizeof(buf));
1186  assert(buf[start_pos-1] == 0xff);
1187 
1188  /*
1189  * fix a problem with mssql2k which doesn't like
1190  * packet splitted during SSL handshake
1191  */
1192  if (tds->out_buf_max < 4096)
1193  tds_realloc_socket(tds, 4096);
1194 
1195  /* do prelogin */
1197 
1198  tds_put_n(tds, buf, start_pos);
1199  /* netlib version */
1200  tds_put_n(tds, IS_TDS72_PLUS(tds->conn) ? netlib9 : netlib8, 6);
1201  /* encryption */
1202 #if !defined(HAVE_GNUTLS) && !defined(HAVE_OPENSSL)
1203  /* not supported */
1204  tds_put_byte(tds, 2);
1205 #else
1207 #endif
1208  /* instance */
1209  tds_put_n(tds, instance_name, instance_name_len);
1210  /* pid */
1211  tds_put_int(tds, getpid());
1212  /* MARS (1 enabled) */
1213  if (IS_TDS72_PLUS(tds->conn))
1214 #if ENABLE_ODBC_MARS
1216  login->mars = 0;
1217 #else
1218  tds_put_byte(tds, 0);
1219 #endif
1220  ret = tds_flush_packet(tds);
1221  if (TDS_FAILED(ret))
1222  return ret;
1223 
1224  /* now process reply from server */
1225  ret = tds_read_packet(tds);
1226  if (ret <= 0 || tds->in_flag != TDS_REPLY)
1227  return TDS_FAIL;
1228  pkt_len = tds->in_len - tds->in_pos;
1229 
1230  /* the only thing we care is flag */
1231  p = tds->in_buf + tds->in_pos;
1232  /* default 2, no certificate, no encryption */
1233  crypt_flag = 2;
1234  for (i = 0;; i += 5) {
1235  TDS_UCHAR type;
1236  int off, len;
1237 
1238  if (i >= pkt_len)
1239  return TDS_FAIL;
1240  type = p[i];
1241  if (type == 0xff)
1242  break;
1243  /* check packet */
1244  if (i+4 >= pkt_len)
1245  return TDS_FAIL;
1246  off = TDS_GET_UA2BE(&p[i+1]);
1247  len = TDS_GET_UA2BE(&p[i+3]);
1248  if (off > pkt_len || (off+len) > pkt_len)
1249  return TDS_FAIL;
1250  if (type == 1 && len >= 1) {
1251  crypt_flag = p[off];
1252  }
1253 #if ENABLE_ODBC_MARS
1254  if (IS_TDS72_PLUS(tds->conn) && type == 4 && len >= 1)
1255  login->mars = p[off];
1256 #endif
1257  }
1258  /* we readed all packet */
1259  tds->in_pos += pkt_len;
1260  /* TODO some mssql version do not set last packet, update tds according */
1261 
1262  tdsdump_log(TDS_DBG_INFO1, "detected flag %d\n", crypt_flag);
1263 
1264  /* if server do not has certificate do normal login */
1265  if (crypt_flag == 2) {
1266  /* unless we wanted encryption and got none, then fail */
1268  return TDS_FAIL;
1269 
1270  return tds7_send_login(tds, login);
1271  }
1272 
1273  /*
1274  * if server has a certificate it require at least a crypted login
1275  * (even if data is not encrypted)
1276  */
1277 
1278  /* here we have to do encryption ... */
1279 
1280  ret = tds_ssl_init(tds);
1281  if (TDS_FAILED(ret))
1282  return ret;
1283 
1284  /* server just encrypt the first packet */
1285  if (crypt_flag == 0)
1287 
1288  ret = tds7_send_login(tds, login);
1289 
1290  /* if flag is 0 it means that after login server continue not encrypted */
1291  if (crypt_flag == 0 || TDS_FAILED(ret))
1293 
1294  return ret;
1295 }
1296 
char PASSWORD[512]
Definition: common.c:31
#define strcat(s, k)
CS_CONTEXT * ctx
Definition: t0006.c:12
static const struct name_t names[]
static int err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
static int msg_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line)
#define TDS_GET_UA2BE(ptr)
Definition: bytes.h:57
#define CHECK_TDS_EXTRA(tds)
Definition: checks.h:31
@ to_server
Definition: iconv.h:70
void * iconv_t
Definition: iconv.h:28
@ TDS71_PRELOGIN
Definition: proto.h:343
@ TDS_REPLY
Definition: proto.h:336
@ TDS7_LOGIN
Definition: proto.h:341
@ TDS_LOGIN
Definition: proto.h:334
#define TDS_PROGNLEN
Definition: proto.h:469
#define TDS_PKTLEN
Definition: proto.h:470
#define TDS_CAPABILITY_TOKEN
Definition: proto.h:104
@ TDS_INTEGRATED_SECURITY_ON
Definition: proto.h:419
@ TDS5_SEC_LOG_ENCRYPT2
Definition: proto.h:479
@ TDS5_SEC_LOG_NONCE
Definition: proto.h:480
#define TDS_MAXNAME
Definition: proto.h:468
@ TDS_USE_DB_NOTIFY
Definition: proto.h:402
@ TDS_DUMPLOAD_OFF
Definition: proto.h:401
@ TDS_SET_LANG_ON
Definition: proto.h:404
@ TDS_INIT_DB_FATAL
Definition: proto.h:403
@ TDS_READONLY_INTENT
Definition: proto.h:433
@ TDS_UNKNOWN_COLLATION_HANDLING
Definition: proto.h:427
@ TDS_CHANGE_PASSWORD
Definition: proto.h:424
#define TDS_FAIL
Definition: tds.h:204
#define tds_new(type, n)
Definition: tds.h:1392
#define TDS_FAILED(rc)
Definition: tds.h:206
#define IS_TDS71_PLUS(x)
Definition: tds.h:1709
tds_sysdep_int32_type TDS_INT
Definition: tds.h:149
#define IS_TDS42(x)
Definition: tds.h:1699
#define tds_set_ctx(tds, val)
Definition: tds.h:1295
@ TDS_RETURN_ROW
Definition: tds.h:256
@ TDS_RETURN_DONE
Definition: tds.h:255
#define TDS_DONE_RESULT
Definition: tds.h:227
@ client2ucs2
Definition: tds.h:1109
#define tdsdump_log
Definition: tds.h:1561
#define TDS_DBG_INFO2
Definition: tds.h:899
#define TDS_DBG_INFO1
Definition: tds.h:900
#define TDS_NO_MORE_RESULTS
Definition: tds.h:202
#define IS_TDS50(x)
Definition: tds.h:1701
#define TDS_MAJOR(x)
Definition: tds.h:1714
#define TDS_DBG_SEVERE
Definition: tds.h:904
#define tds_get_s(tds)
Definition: tds.h:1298
unsigned char TDS_UCHAR
Definition: tds.h:145
#define TDS_INT_CANCEL
Definition: tds.h:210
#define IS_TDS72_PLUS(x)
Definition: tds.h:1710
unsigned char TDS_TINYINT
Definition: tds.h:146
@ TDS_IDLE
no data expected
Definition: tds.h:863
@ TDSEFCON
Definition: tds.h:304
@ TDSECONF
Definition: tds.h:326
@ TDSECONN
Definition: tds.h:309
@ TDSEINTF
Definition: tds.h:311
@ TDSEMEM
Definition: tds.h:310
@ TDSEOK
Definition: tds.h:295
@ TDSEUHST
Definition: tds.h:312
#define TDS_VECTOR_SIZE(x)
Definition: tds.h:360
#define IS_TDS7_PLUS(x)
Definition: tds.h:1708
char TDS_CHAR
Definition: tds.h:144
#define TDS_ROW_RESULT
Definition: tds.h:216
@ TDS_DONE_ERROR
error occurred
Definition: tds.h:272
int(* err_handler_t)(const TDSCONTEXT *, TDSSOCKET *, TDSMESSAGE *)
Definition: tds.h:1095
int TDSRET
Definition: tds.h:201
@ TDS_ENCRYPTION_OFF
Definition: tds.h:356
@ TDS_ENCRYPTION_REQUIRE
Definition: tds.h:356
tds_sysdep_uint16_type TDS_USMALLINT
Definition: tds.h:148
#define TDS_DBG_ERROR
Definition: tds.h:903
#define TDS_SUCCESS
Definition: tds.h:203
#define IS_TDS46(x)
Definition: tds.h:1700
#define TDS_PUT_INT(tds, v)
Definition: tds.h:1742
#define TDS_SUCCEED(rc)
Definition: tds.h:207
tds_sysdep_uint32_type TDS_UINT
Definition: tds.h:150
#define tds_get_ctx(tds)
Definition: tds.h:1294
#define IS_TDS73_PLUS(x)
Definition: tds.h:1711
#define TDS_PUT_SMALLINT(tds, v)
Definition: tds.h:1743
static void tds_ssl_deinit(TDSCONNECTION *conn)
Definition: tls.h:94
static TDSRET tds_ssl_init(TDSSOCKET *tds)
Definition: tls.h:88
static int type
Definition: getdata.c:31
static const char * str(char *buf, int n)
Definition: stats.c:84
static HENV env
Definition: transaction2.c:38
#define addrinfo
Definition: replacements.h:98
#define SYBINT4
Definition: sybdb.h:170
#define SYBINT2
Definition: sybdb.h:168
bool tds_set_user(TDSLOGIN *tds_login, const char *username)
Definition: login.c:100
bool tds_set_server(TDSLOGIN *tds_login, const char *server)
Set the servername in a TDSLOGIN structure.
Definition: login.c:129
#define PUT_STRING_FIELD_PTR(field)
static TDSRET tds71_do_login(TDSSOCKET *tds, TDSLOGIN *login)
Definition: login.c:1139
#define UI16BE(n)
#define START_POS
static void replay_save_context(TDSSOCKET *tds, TDSSAVECONTEXT *ctx)
Definition: login.c:263
bool tds_set_library(TDSLOGIN *tds_login, const char *library)
Definition: login.c:156
static int tds_save_msg(const TDSCONTEXT *ctx, TDSSOCKET *tds, TDSMESSAGE *msg)
Definition: login.c:220
static void tds_save(TDSSAVECONTEXT *ctx, char type, TDSMESSAGE *msg)
Definition: login.c:199
#define SET_UI16BE(i, n)
#define COPY(name)
static TDSRET tds_set_spid(TDSSOCKET *tds)
Retrieve and set @spid \tds.
Definition: login.c:312
int tds_connect_and_login(TDSSOCKET *tds, TDSLOGIN *login)
Definition: login.c:657
static void init_save_context(TDSSAVECONTEXT *ctx, const TDSCONTEXT *old_ctx)
Definition: login.c:254
bool tds_set_app(TDSLOGIN *tds_login, const char *application)
Definition: login.c:112
void tds_set_packet(TDSLOGIN *tds_login, int packet_size)
Definition: login.c:73
struct tds_save_context TDSSAVECONTEXT
static void tds7_crypt_pass(const unsigned char *clear_pass, size_t len, unsigned char *crypt_pass)
tds7_crypt_pass() – 'encrypt' TDS 7.0 style passwords.
Definition: login.c:1130
static int tds_connect(TDSSOCKET *tds, TDSLOGIN *login, int *p_oserr)
Do a connection to socket.
Definition: login.c:367
static int tds_put_login_string(TDSSOCKET *tds, const char *buf, int n)
Definition: login.c:664
bool tds_set_host(TDSLOGIN *tds_login, const char *hostname)
Definition: login.c:106
void tds_set_port(TDSLOGIN *tds_login, int port)
Definition: login.c:79
void tds_set_version(TDSLOGIN *tds_login, TDS_TINYINT major_ver, TDS_TINYINT minor_ver)
Definition: login.c:67
static int tds_save_err(const TDSCONTEXT *ctx, TDSSOCKET *tds, TDSMESSAGE *msg)
Definition: login.c:227
static void tds_save_env(TDSSOCKET *tds, int type, char *oldval, char *newval)
Definition: login.c:234
static TDSRET tds_send_login(TDSSOCKET *tds, TDSLOGIN *login)
Definition: login.c:671
#define SET_FIELD_DSTR(field, dstr)
bool tds_set_client_charset(TDSLOGIN *tds_login, const char *charset)
Definition: login.c:162
bool tds_set_language(TDSLOGIN *tds_login, const char *language)
Definition: login.c:168
static TDSRET tds7_send_login(TDSSOCKET *tds, TDSLOGIN *login)
tds7_send_login() – Send a TDS 7.0 login packet TDS 7.0 login packet is vastly different and so gets ...
Definition: login.c:849
void tds_set_bulk(TDSLOGIN *tds_login, TDS_TINYINT enabled)
Definition: login.c:94
static void reset_save_context(TDSSAVECONTEXT *ctx)
Definition: login.c:284
static void free_save_context(TDSSAVECONTEXT *ctx)
Definition: login.c:302
bool tds_set_passwd(TDSLOGIN *tds_login, const char *password)
Definition: login.c:85
static TDSSOCKET * tds
Definition: collations.c:37
static TDSLOGIN * login
Definition: dataread.c:31
#define tds_put_n
#define tds_iconv_open
#define tds_staticin_stream_init
#define tds_convert_stream
#define tds_gss_get_auth
#define tds_put_int
#define tdsdump_isopen
#define tds_close_socket
#define tds_free_msg
#define tds_process_login_tokens
#define tdsdump_elided
#define tds_ntlm_get_auth
#define tds_put_smallint
#define tds_quote_id
#define tds_dynamic_stream_init
#define tds7_get_instance_port
#define tdsdump_open
#define tds_process_simple_query
#define tds_read_packet
#define tds_flush_packet
#define tds_lookup_host_set
#define tds_put_buf
#define tds_debug_flags
#define tds_submit_query
#define tds_init_write_buf
#define tds5_negotiate_get_auth
#define tds_set_state
#define tds_open_socket
#define tds_put_byte
#define tds_getmac
#define tds_get_conversion_type
#define tdserror
#define tds_realloc_socket
#define tds_process_tokens
char data[12]
Definition: iconv.c:80
#define NULL
Definition: ncbistd.hpp:225
static const char * tds_dstr_cstr(DSTR *s)
Returns a C version (NUL terminated string) of dstr.
Definition: string.h:66
void tds_dstr_zero(DSTR *s)
clear all string filling with zeroes (mainly for security reason)
Definition: tdsstring.c:56
void tds_dstr_free(DSTR *s)
free string
Definition: tdsstring.c:63
DSTR * tds_dstr_copy(DSTR *s, const char *src) TDS_WUR
copy a string from another
Definition: tdsstring.c:123
static int tds_dstr_isempty(DSTR *s)
test if string is empty
Definition: string.h:48
static size_t tds_dstr_len(DSTR *s)
Returns the length of the string in bytes.
Definition: string.h:73
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
char * buf
static int input()
int i
yy_size_t n
int len
const CharType(& source)[N]
Definition: pointer.h:1149
#define strdup
Definition: ncbi_ansi_ext.h:70
#define strcasecmp
#define assert(x)
Definition: srv_diag.hpp:58
TDS_UCHAR * packet
Definition: tds.h:1116
TDSRET(* free)(TDSCONNECTION *conn, struct tds_authentication *auth)
Definition: tds.h:1118
Metadata about columns in regular and compute rows.
Definition: tds.h:761
TDS_INT column_size
maximun size of data.
Definition: tds.h:766
TDS_SERVER_TYPE column_type
This type can be different from wire type because conversion (e.g.
Definition: tds.h:768
unsigned char * column_data
Definition: tds.h:793
TDSENV env
environment is shared between all sessions
Definition: tds.h:1147
char * product_name
Definition: tds.h:1140
TDSICONV ** char_convs
Definition: tds.h:1161
unsigned int encrypt_single_packet
Definition: tds.h:1171
int spid
Definition: tds.h:1192
TDS_USMALLINT tds_version
Definition: tds.h:1138
TDSAUTHENTICATION * authentication
Definition: tds.h:1203
TDS_CAPABILITIES capabilities
Definition: tds.h:1166
unsigned int emul_little_endian
Definition: tds.h:1167
TDSLOCALE * locale
Definition: tds.h:1099
int(* err_handler)(const TDSCONTEXT *, TDSSOCKET *, TDSMESSAGE *)
Definition: tds.h:1103
output stream to write data to a dynamic buffer
Definition: stream.h:99
TDSOUTSTREAM stream
Definition: stream.h:100
size_t size
size of data inside buffer
Definition: stream.h:106
int block_size
packet size (512-65535)
Definition: tds.h:1035
Definition: tds.h:584
unsigned int use_new_password
Definition: tds.h:632
TDS_INT query_timeout
Definition: tds.h:608
DSTR database
Definition: tds.h:611
DSTR client_charset
Definition: tds.h:610
DSTR user_name
account for login
Definition: tds.h:601
TDS_INT connect_timeout
Definition: tds.h:591
struct addrinfo * ip_addrs
ip(s) of server
Definition: tds.h:613
DSTR password
password of account login
Definition: tds.h:602
DSTR db_filename
database filename to attach (MSSQL)
Definition: tds.h:596
TDS_CAPABILITIES capabilities
Definition: tds.h:609
DSTR routing_address
Definition: tds.h:619
unsigned int readonly_intent
Definition: tds.h:635
TDS_TINYINT encryption_level
Definition: tds.h:606
unsigned char option_flag2
Definition: tds.h:622
DSTR client_host_name
Definition: tds.h:592
DSTR dump_file
Definition: tds.h:616
unsigned int valid_configuration
Definition: tds.h:633
DSTR server_name
server name (in freetds.conf)
Definition: tds.h:585
DSTR instance_name
Definition: tds.h:615
DSTR language
Definition: tds.h:589
int debug_flags
Definition: tds.h:617
TDS_USMALLINT tds_version
TDS version.
Definition: tds.h:587
DSTR new_password
new password to set (TDS 7.2+)
Definition: tds.h:603
struct addrinfo * connected_addr
Definition: tds.h:614
unsigned int use_utf16
Definition: tds.h:631
unsigned int suppress_language
Definition: tds.h:625
int text_size
Definition: tds.h:618
unsigned int emul_little_endian
Definition: tds.h:626
unsigned int bulk_copy
if bulk copy should be enabled
Definition: tds.h:624
unsigned int mars
Definition: tds.h:630
TDS_USMALLINT routing_port
Definition: tds.h:620
int port
port of database service
Definition: tds.h:586
int block_size
Definition: tds.h:588
DSTR library
Definition: tds.h:605
DSTR app_name
Definition: tds.h:600
TDS_CHAR * osstr
Definition: tds.h:958
TDSCOLUMN ** columns
Definition: tds.h:844
TDS_USMALLINT num_cols
Definition: tds.h:845
unsigned num_env
Definition: login.c:194
struct tds_save_msg msgs[10]
Definition: login.c:192
TDSCONTEXT ctx
Definition: login.c:189
struct tds_save_env envs[10]
Definition: login.c:195
unsigned num_msg
Definition: login.c:191
char * newval
Definition: login.c:182
char * oldval
Definition: login.c:181
int type
Definition: login.c:183
char type
Definition: login.c:176
TDSMESSAGE msg
Definition: login.c:175
Information for a server connection.
Definition: tds.h:1211
void(* env_chg_func)(TDSSOCKET *tds, int type, char *oldval, char *newval)
Definition: tds.h:1285
unsigned in_len
input buffer length
Definition: tds.h:1239
TDSLOGIN * login
config for login stuff.
Definition: tds.h:1283
unsigned char * in_buf
Input buffer.
Definition: tds.h:1223
unsigned char out_flag
output buffer type
Definition: tds.h:1241
unsigned in_pos
current position in in_buf
Definition: tds.h:1237
TDSCONNECTION conn[1]
Definition: tds.h:1215
TDSRESULTINFO * res_info
Definition: tds.h:1264
unsigned int out_buf_max
Maximum size of packet pointed by out_buf.
Definition: tds.h:1236
TDS_INT query_timeout
Definition: tds.h:1279
input stream to read data from a static buffer
Definition: stream.h:81
Definition: type.c:6
void free(voidpf ptr)
Modified on Thu May 02 14:34:41 2024 by modify_doxy.py rev. 669887