41 #include <sys/socket.h>
61 size_t len,
unsigned char *crypt_pass);
64 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
133 static const char *
names[] = {
"TDSQUERY",
"DSQUERY",
"SYBASE" };
140 source =
"compiled-in default";
142 server = getenv(
names[
i]);
206 dest_msg = &
ctx->msgs[
ctx->num_msg];
210 #define COPY(name) if (msg->name) dest_msg->msg.name = strdup(msg->name);
256 memset(
ctx, 0,
sizeof(*
ctx));
268 for (
n = 0;
n <
ctx->num_msg; ++
n)
269 if (
ctx->msgs[
n].type == 0) {
278 for (
n = 0;
n <
ctx->num_env; ++
n)
289 for (
n = 0;
n <
ctx->num_msg; ++
n)
294 for (
n = 0;
n <
ctx->num_env; ++
n) {
323 switch (result_type) {
370 int connect_timeout = 0;
374 bool rerouted =
false;
397 typedef void (*env_chg_func_t) (
TDSSOCKET *
tds,
int type,
char *oldval,
char *newval);
457 #ifdef WORDS_BIGENDIAN
527 if (addrs->ai_socktype != SOCK_STREAM)
666 const int buf_len =
buf ? (
int)strlen(
buf) : 0;
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 };
677 static const unsigned char le1[] = { 0x03, 0x01, 0x06, 0x0a, 0x09, 0x01 };
678 static const unsigned char le2[] = { 0x00, 13, 17 };
695 unsigned char protocol_version[4];
696 unsigned char program_version[4];
723 memcpy(protocol_version,
"\004\002\000\000", 4);
724 memcpy(program_version,
"\004\002\000\000", 4);
726 memcpy(protocol_version,
"\004\006\000\000", 4);
727 memcpy(program_version,
"\004\002\000\000", 4);
729 memcpy(protocol_version,
"\005\000\000\000", 4);
730 memcpy(program_version,
"\005\000\000\000", 4);
749 sprintf(blockstr,
"%d", (
int) getpid());
751 #ifdef WORDS_BIGENDIAN
792 #ifdef WORDS_BIGENDIAN
825 strcpy(blockstr,
"512");
851 static const unsigned char
852 client_progver[] = { 6, 0x83, 0xf2, 0xf8 },
854 connection_id[] = { 0x00, 0x00, 0x00, 0x00 },
855 collation[] = { 0x36, 0x04, 0x00, 0x00 };
858 tds70Version = 0x70000000,
859 tds71Version = 0x71000001,
860 tds72Version = 0x72090002,
861 tds73Version = 0x730B0003,
862 tds74Version = 0x74000004,
866 TDS_INT tds7version = tds70Version;
868 unsigned int block_size = 4096;
872 unsigned char option_flag3 = 0;
874 unsigned char hwaddr[6];
875 size_t packet_size, current_pos;
886 size_t user_name_len = strlen(user_name);
906 } data_fields[NUM_DATA_FIELDS], *field;
914 if (strchr(user_name,
'\\') !=
NULL || user_name_len == 0) {
920 packet_size += auth_len;
922 if (strchr(user_name,
'\\') !=
NULL) {
928 packet_size += auth_len;
929 }
else if (user_name_len == 0) {
937 packet_size += auth_len;
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); \
959 data_fields[USER_NAME].len = 0;
971 data_fields[NEW_PASSWORD].len = 0;
978 for (field = data_fields; field < data_fields +
TDS_VECTOR_SIZE(data_fields); ++field) {
981 data_pos = data_stream.
size;
982 field->pos = current_pos + data_pos;
991 field->len = data_stream.
size - data_pos;
993 pwd = (
unsigned char *) data + data_fields[
PASSWORD].pos - current_pos;
995 pwd = (
unsigned char *) data + data_fields[NEW_PASSWORD].pos - current_pos;
997 packet_size += data_stream.
size;
999 #if !defined(TDS_DEBUG_LOGIN)
1006 tds7version = tds70Version;
1009 tds7version = tds71Version;
1012 tds7version = tds72Version;
1015 tds7version = tds73Version;
1018 tds7version = tds74Version;
1034 tds_put_n(
tds, client_progver,
sizeof(client_progver));
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); \
1134 for (
i = 0;
i <
len;
i++)
1135 crypt_pass[
i] = ((clear_pass[
i] << 4) | (clear_pass[
i] >> 4)) ^ 0xA5;
1143 TDS_USMALLINT instance_name_len = strlen(instance_name) + 1;
1145 unsigned int start_pos = 21;
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)
1165 static const TDS_UCHAR netlib8[] = { 8, 0, 1, 0x55, 0, 0 };
1166 static const TDS_UCHAR netlib9[] = { 9, 0, 0, 0, 0, 0 };
1177 #define START_POS 26
1185 assert(start_pos >= 21 && start_pos <=
sizeof(
buf));
1202 #if !defined(HAVE_GNUTLS) && !defined(HAVE_OPENSSL)
1214 #if ENABLE_ODBC_MARS
1226 if (ret <= 0 || tds->in_flag !=
TDS_REPLY)
1234 for (
i = 0;;
i += 5) {
1248 if (off > pkt_len || (off+
len) > pkt_len)
1251 crypt_flag = p[off];
1253 #if ENABLE_ODBC_MARS
1265 if (crypt_flag == 2) {
1285 if (crypt_flag == 0)
#define TDS_GET_UA2BE(ptr)
#define CHECK_TDS_EXTRA(tds)
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)
static const char * tds_dstr_cstr(DSTR *s)
Returns a C version (NUL terminated string) of dstr.
void tds_dstr_zero(DSTR *s)
clear all string filling with zeroes (mainly for security reason)
void tds_dstr_free(DSTR *s)
free string
DSTR * tds_dstr_copy(DSTR *s, const char *src) TDS_WUR
copy a string from another
static int tds_dstr_isempty(DSTR *s)
test if string is empty
static size_t tds_dstr_len(DSTR *s)
Returns the length of the string in bytes.
unsigned int
A callback function used to compare two keys in a database.
bool tds_set_user(TDSLOGIN *tds_login, const char *username)
bool tds_set_server(TDSLOGIN *tds_login, const char *server)
Set the servername in a TDSLOGIN structure.
#define PUT_STRING_FIELD_PTR(field)
static TDSRET tds71_do_login(TDSSOCKET *tds, TDSLOGIN *login)
static void replay_save_context(TDSSOCKET *tds, TDSSAVECONTEXT *ctx)
bool tds_set_library(TDSLOGIN *tds_login, const char *library)
static int tds_save_msg(const TDSCONTEXT *ctx, TDSSOCKET *tds, TDSMESSAGE *msg)
static void tds_save(TDSSAVECONTEXT *ctx, char type, TDSMESSAGE *msg)
static TDSRET tds_set_spid(TDSSOCKET *tds)
Retrieve and set @spid \tds.
int tds_connect_and_login(TDSSOCKET *tds, TDSLOGIN *login)
static void init_save_context(TDSSAVECONTEXT *ctx, const TDSCONTEXT *old_ctx)
bool tds_set_app(TDSLOGIN *tds_login, const char *application)
void tds_set_packet(TDSLOGIN *tds_login, int packet_size)
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.
static int tds_connect(TDSSOCKET *tds, TDSLOGIN *login, int *p_oserr)
Do a connection to socket.
static int tds_put_login_string(TDSSOCKET *tds, const char *buf, int n)
bool tds_set_host(TDSLOGIN *tds_login, const char *hostname)
void tds_set_port(TDSLOGIN *tds_login, int port)
void tds_set_version(TDSLOGIN *tds_login, TDS_TINYINT major_ver, TDS_TINYINT minor_ver)
static int tds_save_err(const TDSCONTEXT *ctx, TDSSOCKET *tds, TDSMESSAGE *msg)
static void tds_save_env(TDSSOCKET *tds, int type, char *oldval, char *newval)
static TDSRET tds_send_login(TDSSOCKET *tds, TDSLOGIN *login)
#define SET_FIELD_DSTR(field, dstr)
bool tds_set_client_charset(TDSLOGIN *tds_login, const char *charset)
bool tds_set_language(TDSLOGIN *tds_login, const char *language)
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 ...
void tds_set_bulk(TDSLOGIN *tds_login, TDS_TINYINT enabled)
static void reset_save_context(TDSSAVECONTEXT *ctx)
static void free_save_context(TDSSAVECONTEXT *ctx)
bool tds_set_passwd(TDSLOGIN *tds_login, const char *password)
const CharType(& source)[N]
#define TDS_CAPABILITY_TOKEN
@ TDS_INTEGRATED_SECURITY_ON
@ TDS_UNKNOWN_COLLATION_HANDLING
#define tds_staticin_stream_init
#define tds_convert_stream
#define tds_process_login_tokens
#define tds_ntlm_get_auth
#define tds_dynamic_stream_init
#define tds7_get_instance_port
#define tds_process_simple_query
#define tds_lookup_host_set
#define tds_init_write_buf
#define tds5_negotiate_get_auth
#define tds_get_conversion_type
#define tds_realloc_socket
#define tds_process_tokens
static const char * str(char *buf, int n)
TDSRET(* free)(TDSCONNECTION *conn, struct tds_authentication *auth)
Metadata about columns in regular and compute rows.
TDS_INT column_size
maximun size of data.
unsigned char * column_data
TDS_SERVER_TYPE column_type
This type can be different from wire type because conversion (e.g.
TDSENV env
environment is shared between all sessions
TDSAUTHENTICATION * authentication
unsigned int encrypt_single_packet
TDS_USMALLINT tds_version
TDS_CAPABILITIES capabilities
unsigned int emul_little_endian
int(* err_handler)(const TDSCONTEXT *, TDSSOCKET *, TDSMESSAGE *)
output stream to write data to a dynamic buffer
size_t size
size of data inside buffer
int block_size
packet size (512-65535)
unsigned int use_new_password
DSTR user_name
account for login
DSTR password
password of account login
DSTR db_filename
database filename to attach (MSSQL)
TDS_CAPABILITIES capabilities
unsigned int readonly_intent
TDS_TINYINT encryption_level
unsigned char option_flag2
unsigned int valid_configuration
DSTR server_name
server name (in freetds.conf)
struct addrinfo * ip_addrs
ip(s) of server
TDS_USMALLINT tds_version
TDS version.
DSTR new_password
new password to set (TDS 7.2+)
struct addrinfo * connected_addr
unsigned int suppress_language
unsigned int emul_little_endian
unsigned int bulk_copy
if bulk copy should be enabled
TDS_USMALLINT routing_port
int port
port of database service
struct tds_save_msg msgs[10]
struct tds_save_env envs[10]
Information for a server connection.
TDSLOGIN * login
config for login stuff.
unsigned in_len
input buffer length
unsigned char * in_buf
Input buffer.
void(* env_chg_func)(TDSSOCKET *tds, int type, char *oldval, char *newval)
unsigned char out_flag
output buffer type
unsigned in_pos
current position in in_buf
unsigned int out_buf_max
Maximum size of packet pointed by out_buf.
input stream to read data from a static buffer
Main include file for libtds.
tds_sysdep_int32_type TDS_INT
#define tds_set_ctx(tds, val)
#define TDS_NO_MORE_RESULTS
unsigned char TDS_TINYINT
@ TDS_IDLE
no data expected
#define TDS_VECTOR_SIZE(x)
@ TDS_DONE_ERROR
error occurred
int(* err_handler_t)(const TDSCONTEXT *, TDSSOCKET *, TDSMESSAGE *)
tds_sysdep_uint16_type TDS_USMALLINT
#define TDS_PUT_INT(tds, v)
TDSAUTHENTICATION * tds_gss_get_auth(TDSSOCKET *tds)
tds_sysdep_uint32_type TDS_UINT
#define TDS_PUT_SMALLINT(tds, v)
static void tds_ssl_deinit(TDSCONNECTION *conn)
static TDSRET tds_ssl_init(TDSSOCKET *tds)