void tds_send_eed(TDSSOCKET * tds, int msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line) { int totsize; tds_put_byte(tds, TDS_EED_TOKEN); totsize = 7 + strlen(procname) + 5 + strlen(msgtext) + 2 + strlen(srvname) + 3; tds_put_smallint(tds, totsize); tds_put_smallint(tds, msgno); tds_put_smallint(tds, 0); /* unknown */ tds_put_byte(tds, msgstate); tds_put_byte(tds, severity); tds_put_byte(tds, strlen(procname)); tds_put_n(tds, procname, strlen(procname)); tds_put_byte(tds, 0); /* unknown */ tds_put_byte(tds, 1); /* unknown */ tds_put_byte(tds, 0); /* unknown */ tds_put_smallint(tds, strlen(msgtext) + 1); tds_put_n(tds, msgtext, strlen(msgtext)); tds_put_byte(tds, severity); tds_put_byte(tds, strlen(srvname)); tds_put_n(tds, srvname, strlen(srvname)); tds_put_byte(tds, 0); /* unknown */ tds_put_byte(tds, 1); /* unknown */ tds_put_byte(tds, 0); /* unknown */ }
void tds_send_login_ack(TDSSOCKET * tds, const char *progname) { TDS_UINT ui, version; tds_put_byte(tds, TDS_LOGINACK_TOKEN); tds_put_smallint(tds, 10 + (IS_TDS7_PLUS(tds->conn)? 2 : 1) * strlen(progname)); /* length of message */ if (IS_TDS50(tds->conn)) { tds_put_byte(tds, 5); version = 0x05000000u; } else { tds_put_byte(tds, 1); /* see src/tds/token.c */ if (IS_TDS73_PLUS(tds->conn)) { version = 0x730B0003u; } else if (IS_TDS72_PLUS(tds->conn)) { version = 0x72090002u; } else if (IS_TDS71_PLUS(tds->conn)) { version = tds->conn->tds71rev1 ? 0x07010000u : 0x71000001u; } else { version = (TDS_MAJOR(tds->conn) << 24) | (TDS_MINOR(tds->conn) << 16); } } TDS_PUT_A4BE(&ui, version); tds_put_n(tds, &ui, 4); tds_put_byte(tds, strlen(progname)); /* FIXME ucs2 */ tds_put_string(tds, progname, strlen(progname)); /* server version, always big endian */ TDS_PUT_A4BE(&ui, tds->conn->product_version & 0x7fffffffu); tds_put_n(tds, &ui, 4); }
void tds_env_change(TDSSOCKET * tds, int type, const char *oldvalue, const char *newvalue) { TDS_SMALLINT totsize; /* If oldvalue is NULL, treat it like "" */ if (oldvalue == NULL) oldvalue = ""; /* * NOTE: I don't know why each type of environment value has a different * format. According to the TDS5 specifications, they should all use * the same format. The code for the TDS_ENV_CHARSET case *should* * work for all environment values. -- Steve Kirkendall */ switch (type) { case TDS_ENV_DATABASE: case TDS_ENV_LANG: case TDS_ENV_PACKSIZE: case TDS_ENV_CHARSET: tds_put_byte(tds, TDS_ENVCHANGE_TOKEN); /* totsize = type + newlen + newvalue + oldlen + oldvalue */ /* FIXME ucs2 */ totsize = (IS_TDS7_PLUS(tds->conn) ? 2 : 1) * (strlen(oldvalue) + strlen(newvalue)) + 3; tds_put_smallint(tds, totsize); tds_put_byte(tds, type); tds_put_byte(tds, strlen(newvalue)); /* FIXME this assume singlebyte -> ucs2 for mssql */ tds_put_string(tds, newvalue, strlen(newvalue)); tds_put_byte(tds, strlen(oldvalue)); /* FIXME this assume singlebyte -> ucs2 for mssql */ tds_put_string(tds, oldvalue, strlen(oldvalue)); break; case TDS_ENV_LCID: case TDS_ENV_SQLCOLLATION: #if 1 tds_put_byte(tds, TDS_ENVCHANGE_TOKEN); /* totsize = type + len + oldvalue + len + newvalue */ totsize = 3 + strlen(newvalue) + strlen(oldvalue); tds_put_smallint(tds, totsize); tds_put_byte(tds, type); tds_put_byte(tds, strlen(newvalue)); tds_put_n(tds, newvalue, strlen(newvalue)); tds_put_byte(tds, strlen(oldvalue)); tds_put_n(tds, oldvalue, strlen(oldvalue)); break; #endif default: tdsdump_log(TDS_DBG_WARN, "tds_env_change() ignoring unsupported environment code #%d", type); } }
void tds_send_result(TDSSOCKET * tds, TDSRESULTINFO * resinfo) { TDSCOLUMN *curcol; int i, totlen; size_t len; tds_put_byte(tds, TDS_RESULT_TOKEN); totlen = 2; for (i = 0; i < resinfo->num_cols; i++) { curcol = resinfo->columns[i]; len = tds_dstr_len(&curcol->column_name); totlen += 8; totlen += len; curcol = resinfo->columns[i]; if (!is_fixed_type(curcol->column_type)) { totlen++; } } tds_put_smallint(tds, totlen); tds_put_smallint(tds, resinfo->num_cols); for (i = 0; i < resinfo->num_cols; i++) { curcol = resinfo->columns[i]; len = tds_dstr_len(&curcol->column_name); tds_put_byte(tds, tds_dstr_len(&curcol->column_name)); tds_put_n(tds, tds_dstr_cstr(&curcol->column_name), len); tds_put_byte(tds, '0'); tds_put_int(tds, curcol->column_usertype); tds_put_byte(tds, curcol->column_type); if (!is_fixed_type(curcol->column_type)) { tds_put_byte(tds, curcol->column_size); } tds_put_byte(tds, 0); } }
void tds_send_col_info(TDSSOCKET * tds, TDSRESULTINFO * resinfo) { int col, hdrsize = 0; TDSCOLUMN *curcol; tds_put_byte(tds, TDS_COLFMT_TOKEN); for (col = 0; col < resinfo->num_cols; col++) { curcol = resinfo->columns[col]; hdrsize += 5; if (!is_fixed_type(curcol->column_type)) { hdrsize++; } } tds_put_smallint(tds, hdrsize); for (col = 0; col < resinfo->num_cols; col++) { curcol = resinfo->columns[col]; tds_put_n(tds, "\0\0\0\0", 4); tds_put_byte(tds, curcol->column_type); if (!is_fixed_type(curcol->column_type)) { tds_put_byte(tds, curcol->column_size); } } }
void tds_send_row(TDSSOCKET * tds, TDSRESULTINFO * resinfo) { TDSCOLUMN *curcol; int colsize, i; tds_put_byte(tds, TDS_ROW_TOKEN); for (i = 0; i < resinfo->num_cols; i++) { curcol = resinfo->columns[i]; if (!is_fixed_type(curcol->column_type)) { /* FIX ME -- I have no way of knowing the actual length of non character variable data (eg nullable int) */ colsize = strlen((char *) curcol->column_data); tds_put_byte(tds, colsize); tds_put_n(tds, curcol->column_data, colsize); } else { tds_put_n(tds, curcol->column_data, tds_get_size_by_type(curcol->column_type)); } } }
static SSL_RET tds_push_func_login(SSL_PUSH_ARGS) { TDSSOCKET *tds = (TDSSOCKET *) SSL_PTR; tdsdump_log(TDS_DBG_INFO1, "in tds_push_func_login\n"); /* initializing SSL, write crypted data inside normal TDS packets */ tds_put_n(tds, data, len); return len; }
void tds71_send_prelogin(TDSSOCKET * tds) { static const unsigned char prelogin[] = { 0x00, 0x00, 0x15, 0x00, 0x06, 0x01, 0x00, 0x1b, 0x00, 0x01, 0x02, 0x00, 0x1c, 0x00, 0x01, 0x03, 0x00, 0x1d, 0x00, 0x00, 0xff, 0x08, 0x00, 0x01, 0x55, 0x00, 0x00, 0x02, 0x00 }; tds_put_n(tds, prelogin, sizeof(prelogin)); }
static int tds_sspi_handle_next(TDSSOCKET * tds, struct tds_authentication * tds_auth, size_t len) { SecBuffer in_buf, out_buf; SecBufferDesc in_desc, out_desc; SECURITY_STATUS status; ULONG attrs; TimeStamp ts; TDS_UCHAR *auth_buf; TDSSSPIAUTH *auth = (TDSSSPIAUTH *) tds_auth; if (len < 32 || len > NTLMBUF_LEN) return TDS_FAIL; auth_buf = (TDS_UCHAR *) malloc(len); if (!auth_buf) return TDS_FAIL; tds_get_n(tds, auth_buf, (int)len); in_desc.ulVersion = out_desc.ulVersion = SECBUFFER_VERSION; in_desc.cBuffers = out_desc.cBuffers = 1; in_desc.pBuffers = &in_buf; out_desc.pBuffers = &out_buf; in_buf.BufferType = SECBUFFER_TOKEN; in_buf.pvBuffer = auth_buf; in_buf.cbBuffer = (ULONG)len; out_buf.BufferType = SECBUFFER_TOKEN; out_buf.pvBuffer = auth->tds_auth.packet; out_buf.cbBuffer = NTLMBUF_LEN; status = sec_fn->InitializeSecurityContextA(&auth->cred, &auth->cred_ctx, auth->sname, ISC_REQ_CONFIDENTIALITY | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONNECTION, 0, SECURITY_NETWORK_DREP, &in_desc, 0, &auth->cred_ctx, &out_desc, &attrs, &ts); free(auth_buf); if (status != SEC_E_OK) return TDS_FAIL; if (out_buf.cbBuffer == 0) return TDS_SUCCEED; tds_put_n(tds, auth->tds_auth.packet, out_buf.cbBuffer); return tds_flush_packet(tds); }
void tds_send_col_name(TDSSOCKET * tds, TDSRESULTINFO * resinfo) { int col, hdrsize = 0; TDSCOLUMN *curcol; tds_put_byte(tds, TDS_COLNAME_TOKEN); for (col = 0; col < resinfo->num_cols; col++) { curcol = resinfo->columns[col]; hdrsize += tds_dstr_len(&curcol->column_name) + 1; } tds_put_smallint(tds, hdrsize); for (col = 0; col < resinfo->num_cols; col++) { curcol = resinfo->columns[col]; tds_put_byte(tds, tds_dstr_len(&curcol->column_name)); /* exclude the null */ tds_put_n(tds, tds_dstr_cstr(&curcol->column_name), tds_dstr_len(&curcol->column_name)); } }
void tds_send_col_name(TDSSOCKET * tds, TDSRESULTINFO * resinfo) { int col, hdrsize = 0; TDSCOLUMN *curcol; tds_put_byte(tds, TDS_COLNAME_TOKEN); for (col = 0; col < resinfo->num_cols; col++) { curcol = resinfo->columns[col]; assert(strlen(curcol->column_name) == curcol->column_namelen); hdrsize += curcol->column_namelen + 1; } tds_put_smallint(tds, hdrsize); for (col = 0; col < resinfo->num_cols; col++) { curcol = resinfo->columns[col]; tds_put_byte(tds, curcol->column_namelen); /* exclude the null */ tds_put_n(tds, curcol->column_name, curcol->column_namelen); } }
static TDSRET tds_gss_handle_next(TDSSOCKET * tds, struct tds_authentication * auth, size_t len) { TDSRET res; gss_buffer_desc recv_tok; if (((struct tds_gss_auth *) auth)->last_stat != GSS_S_CONTINUE_NEEDED) return TDS_FAIL; if (auth->packet) { OM_uint32 min_stat; gss_buffer_desc send_tok; send_tok.value = (void *) auth->packet; send_tok.length = auth->packet_len; gss_release_buffer(&min_stat, &send_tok); auth->packet = NULL; } recv_tok.length = len; recv_tok.value = (char* ) malloc(len); if (!recv_tok.value) return TDS_FAIL; tds_get_n(tds, recv_tok.value, len); res = tds_gss_continue(tds, (struct tds_gss_auth *) auth, &recv_tok); free(recv_tok.value); if (TDS_FAILED(res)) return res; if (auth->packet_len) { tds->out_flag = TDS7_AUTH; tds_put_n(tds, auth->packet, auth->packet_len); return tds_flush_packet(tds); } return TDS_SUCCESS; }
int main(int argc, char **argv) { TDSLOGIN *login; TDSSOCKET *tds; int ret; int verbose = 0; TDS_INT8 i8; unsigned limit; fprintf(stdout, "%s: Testing login, logout\n", __FILE__); ret = try_tds_login(&login, &tds, __FILE__, verbose); if (ret != TDS_SUCCESS) { fprintf(stderr, "try_tds_login() failed\n"); return 1; } unfinished_query_test(tds); tds->out_flag = TDS_QUERY; if (tds_set_state(tds, TDS_WRITING) != TDS_WRITING) { return 1; } tds_put_n(tds, "aaa", 3); limit = tds->out_buf_max / 8 + 100; for (i8 = 0; i8 < limit; ++i8) { CHECK_TDS_EXTRA(tds); tds_put_int8(tds, i8); } tds_send_cancel(tds); tds_process_simple_query(tds); try_tds_logout(login, tds, verbose); return 0; }
/** * Send one row of data to server * \tds * \param bcpinfo BCP information * \param get_col_data function to call to retrieve data to be sent * \param ignored function to call if we try to send NULL if not allowed (not used) * \param offset passed to get_col_data and null_error to specify the row to get * \return TDS_SUCCESS or TDS_FAIL. */ TDSRET tds_bcp_send_record(TDSSOCKET *tds, TDSBCPINFO *bcpinfo, tds_bcp_get_col_data get_col_data, tds_bcp_null_error null_error, int offset) { TDSCOLUMN *bindcol; int i, start_col = bcpinfo->next_col; TDSRET rc; tdsdump_log(TDS_DBG_FUNC, "tds_bcp_send_bcp_record(%p, %p, %p, %p, %d)\n", tds, bcpinfo, get_col_data, null_error, offset); if (tds->out_flag != TDS_BULK || tds_set_state(tds, TDS_WRITING) != TDS_WRITING) return TDS_FAIL; if (start_col > 0) { bindcol = bcpinfo->bindinfo->columns[start_col - 1]; *bindcol->column_lenbind = MIN((TDS_INT) bindcol->column_bindlen - bcpinfo->text_sent, *bindcol->column_lenbind); tds_put_n(tds, bindcol->column_varaddr, *bindcol->column_lenbind); bcpinfo->text_sent += *bindcol->column_lenbind; if ((TDS_UINT) bcpinfo->text_sent < bindcol->column_bindlen) { return TDS_SUCCESS; /* That's all for now. */ } else if (!IS_TDS7_PLUS(tds->conn)) { bcpinfo->blob_cols++; } bcpinfo->next_col = 0; bcpinfo->text_sent = 0; } if (IS_TDS7_PLUS(tds->conn)) { if (start_col == 0) { tds_put_byte(tds, TDS_ROW_TOKEN); /* 0xd1 */ } for (i = start_col; i < bcpinfo->bindinfo->num_cols; i++) { TDS_INT save_size; unsigned char *save_data; TDSBLOB blob; int /* bool */ has_text = 0; bindcol = bcpinfo->bindinfo->columns[i]; /* * Don't send the (meta)data for timestamp columns or * identity columns unless indentity_insert is enabled. */ if ((!bcpinfo->identity_insert_on && bindcol->column_identity) || bindcol->column_timestamp || !tds_bcp_is_bound(bcpinfo, bindcol)) { continue; } rc = get_col_data(bcpinfo, bindcol, offset); if (rc == TDS_FAIL) { tdsdump_log(TDS_DBG_INFO1, "get_col_data (column %d) failed\n", i + 1); goto cleanup; } else if (rc != TDS_SUCCESS) { /* CS_BLK_HAS_TEXT? */ has_text = 1; } tdsdump_log(TDS_DBG_INFO1, "gotten column %d length %d null %d\n", i + 1, bindcol->bcp_column_data->datalen, bindcol->bcp_column_data->is_null); save_size = bindcol->column_cur_size; save_data = bindcol->column_data; assert(bindcol->column_data == NULL); if (bindcol->bcp_column_data->is_null) { if ( !bindcol->column_nullable && !is_nullable_type(bindcol->on_server.column_type) ) { return TDS_FAIL; } bindcol->column_cur_size = -1; } else if (has_text) { bindcol->column_cur_size = bindcol->bcp_column_data->datalen; } else if (is_blob_col(bindcol)) { bindcol->column_cur_size = bindcol->bcp_column_data->datalen; memset(&blob, 0, sizeof(blob)); blob.textvalue = (TDS_CHAR *) bindcol->bcp_column_data->data; bindcol->column_data = (unsigned char *) &blob; } else { bindcol->column_cur_size = bindcol->bcp_column_data->datalen; bindcol->column_data = bindcol->bcp_column_data->data; } rc = bindcol->funcs->put_data(tds, bindcol, 1); bindcol->column_cur_size = save_size; bindcol->column_data = save_data; if (TDS_FAILED(rc)) goto cleanup; else if (has_text) { bcpinfo->next_col = i + 1; /* bcpinfo->text_sent = 0; */ break; } } } /* IS_TDS7_PLUS */ else { if (start_col == 0) { int row_pos; int row_sz_pos; int var_cols_written = 0; TDS_INT old_record_size = bcpinfo->bindinfo->row_size; unsigned char *record = bcpinfo->bindinfo->current_row; memset(record, '\0', old_record_size); /* zero the rowbuffer */ /* * offset 0 = number of var columns * offset 1 = row number. zeroed (datasever assigns) */ row_pos = 2; rc = TDS_FAIL; if ((row_pos = tds_bcp_add_fixed_columns(bcpinfo, get_col_data, null_error, offset, record, row_pos)) < 0) goto cleanup; row_sz_pos = row_pos; /* potential variable columns to write */ if ((row_pos = tds_bcp_add_variable_columns(bcpinfo, get_col_data, null_error, offset, record, row_pos, &var_cols_written)) < 0) goto cleanup; if (var_cols_written) { TDS_PUT_UA2(&record[row_sz_pos], row_pos); record[0] = var_cols_written; } tdsdump_log(TDS_DBG_INFO1, "old_record_size = %d new size = %d \n", old_record_size, row_pos); tds_put_smallint(tds, row_pos); tds_put_n(tds, record, row_pos); /* row is done, now handle any text/image data */ bcpinfo->blob_cols = 0; } for (i = start_col; i < bcpinfo->bindinfo->num_cols; i++) { bindcol = bcpinfo->bindinfo->columns[i]; if (is_blob_type(bindcol->column_type)) { /* Elide trailing NULLs */ if (bindcol->bcp_column_data->is_null) { int j; for (j = i + 1; j < bcpinfo->bindinfo->num_cols; ++j) { TDSCOLUMN *bindcol2 = bcpinfo->bindinfo->columns[j]; if (is_blob_type(bindcol2->column_type) && !bindcol2->bcp_column_data->is_null) { break; } } if (j == bcpinfo->bindinfo->num_cols) { i = j; break; } } rc = get_col_data(bcpinfo, bindcol, offset); if (rc == TDS_FAIL) goto cleanup; /* unknown but zero */ tds_put_smallint(tds, 0); tds_put_byte(tds, (unsigned char) bindcol->column_type); tds_put_byte(tds, 0xff - bcpinfo->blob_cols); /* * offset of txptr we stashed during variable * column processing */ tds_put_smallint(tds, bindcol->column_textpos); tds_put_int(tds, bindcol->bcp_column_data->datalen); if (rc != TDS_SUCCESS) { /* CS_BLK_HAS_TEXT? */ bcpinfo->next_col = i + 1; /* bcpinfo->text_sent = 0; */ break; } tds_put_n(tds, bindcol->bcp_column_data->data, bindcol->bcp_column_data->datalen); bcpinfo->blob_cols++; } } } if (i == bcpinfo->bindinfo->num_cols) { tds_set_state(tds, TDS_SENDING); bcpinfo->next_col = 0; } return TDS_SUCCESS; cleanup: tds_set_state(tds, TDS_SENDING); return rc; }
static TDSRET tds5_negotiate_handle_next(TDSSOCKET * tds, TDSAUTHENTICATION * tds_auth, size_t len) { TDS5NEGOTIATE *auth = (TDS5NEGOTIATE *) tds_auth; TDSPARAMINFO *info; void *rsa, *nonce = NULL; size_t rsa_len, nonce_len = 0; void *em; size_t em_size; TDSRET rc = TDS_FAIL; /* send next data for authentication */ if (!tds->login) goto error; /* we only support RSA authentication, we should have send 2/3 parameters: * 1- integer.. unknown actually 1 TODO * 2- binary, rsa public key in PEM format * 3- binary, nonce (optional) */ /* message not supported */ if (auth->msg_type != 0x1e) goto error; info = tds->param_info; if (!info || info->num_cols < 2) goto error; if (info->columns[1]->column_type != SYBLONGBINARY) goto error; if (info->num_cols >= 3 && info->columns[2]->column_type != SYBLONGBINARY) goto error; rsa = ((TDSBLOB*) info->columns[1]->column_data)->textvalue; rsa_len = info->columns[1]->column_size; if (info->num_cols >= 3) { nonce = ((TDSBLOB*) info->columns[2]->column_data)->textvalue; nonce_len = info->columns[2]->column_size; } em = tds5_rsa_encrypt(rsa, rsa_len, nonce, nonce_len, tds_dstr_cstr(&tds->login->password), &em_size); if (!em) goto error; tds->out_flag = TDS_NORMAL; /* password */ tds5_send_msg(tds, 0x1f); tds_put_n(tds, "\xec\x0e\x00\x01\x00\x00\x00\x00\x00\x00\x00\xe1\xff\xff\xff\x7f\x00", 0x11); tds_put_byte(tds, TDS5_PARAMS_TOKEN); tds_put_int(tds, em_size); tds_put_n(tds, em, em_size); /* remote password */ tds5_send_msg(tds, 0x20); tds_put_n(tds, "\xec\x17\x00\x02\x00\x00\x00\x00\x00\x00\x00\x27\xff\x00\x00\x00\x00\x00\x00\x00\xe1\xff\xff\xff\x7f\x00", 0x1a); tds_put_byte(tds, TDS5_PARAMS_TOKEN); tds_put_byte(tds, 0); tds_put_int(tds, em_size); tds_put_n(tds, em, em_size); free(em); rc = tds_flush_packet(tds); error: tds5_negotiate_free(tds->conn, tds_auth); tds->conn->authentication = NULL; return rc; }
/* * pool_user_login * Reads clients login packet and forges a login acknowledgement sequence */ static bool pool_user_login(TDS_POOL * pool, TDS_POOL_USER * puser) { TDSSOCKET *tds; TDSLOGIN *login; tds = puser->sock.tds; while (tds->in_len <= tds->in_pos) if (tds_read_packet(tds) < 0) return false; tdsdump_log(TDS_DBG_NETWORK, "got packet type %d\n", tds->in_flag); if (tds->in_flag == TDS71_PRELOGIN) { if (!tds->conn->tds_version) tds->conn->tds_version = 0x701; tds->out_flag = TDS_REPLY; // TODO proper one !! // TODO detect TDS version here ?? tds_put_n(tds, "\x00\x00\x1a\x00\x06" /* version */ "\x01\x00\x20\x00\x01" /* encryption */ "\x02\x00\x21\x00\x01" /* instance ?? */ "\x03\x00\x22\x00\x00" /* process id ?? */ "\x04\x00\x22\x00\x01" /* MARS */ "\xff" "\x0a\x00\x06\x40\x00\x00" "\x02" "\x01" "" "\x00", 0x23); tds_flush_packet(tds); /* read another packet */ tds->in_pos = tds->in_len; while (tds->in_len <= tds->in_pos) if (tds_read_packet(tds) < 0) return false; } puser->login = login = tds_alloc_login(1); if (tds->in_flag == TDS_LOGIN) { if (!tds->conn->tds_version) tds->conn->tds_version = 0x500; tds_read_login(tds, login); } else if (tds->in_flag == TDS7_LOGIN) { if (!tds->conn->tds_version) tds->conn->tds_version = 0x700; if (!tds7_read_login(tds, login)) return false; } else { return false; } /* check we support version required */ // TODO function to check it if (!IS_TDS71_PLUS(login)) return false; tds->in_len = tds->in_pos = 0; dump_login(login); if (strcmp(tds_dstr_cstr(&login->user_name), pool->user) != 0 || strcmp(tds_dstr_cstr(&login->password), pool->password) != 0) /* TODO send nack before exiting */ return false; return true; }
bool pool_user_send_login_ack(TDS_POOL * pool, TDS_POOL_USER * puser) { char msg[256]; char block[32]; TDSSOCKET *tds = puser->sock.tds, *mtds = puser->assigned_member->sock.tds; TDSLOGIN *login = puser->login; const char *database; const char *server = mtds->conn->server ? mtds->conn->server : "JDBC"; bool dbname_mismatch, odbc_mismatch; pool->user_logins++; /* copy a bit of information, resize socket with block */ tds->conn->tds_version = mtds->conn->tds_version; tds->conn->product_version = mtds->conn->product_version; memcpy(tds->conn->collation, mtds->conn->collation, sizeof(tds->conn->collation)); tds->conn->tds71rev1 = mtds->conn->tds71rev1; free(tds->conn->product_name); tds->conn->product_name = strdup(mtds->conn->product_name); tds_realloc_socket(tds, mtds->conn->env.block_size); tds->conn->env.block_size = mtds->conn->env.block_size; tds->conn->client_spid = mtds->conn->spid; /* if database is different use USE statement */ database = pool->database; dbname_mismatch = !tds_dstr_isempty(&login->database) && strcasecmp(tds_dstr_cstr(&login->database), database) != 0; odbc_mismatch = (login->option_flag2 & TDS_ODBC_ON) == 0; if (dbname_mismatch || odbc_mismatch) { char *str; int len = 128 + tds_quote_id(mtds, NULL, tds_dstr_cstr(&login->database),-1); TDSRET ret; if ((str = (char *) malloc(len)) == NULL) return false; str[0] = 0; /* swicth to dblib options */ if (odbc_mismatch) strcat(str, "SET ANSI_DEFAULTS OFF\nSET CONCAT_NULL_YIELDS_NULL OFF\n"); if (dbname_mismatch) { strcat(str, "USE "); tds_quote_id(mtds, strchr(str, 0), tds_dstr_cstr(&login->database), -1); } ret = tds_submit_query(mtds, str); free(str); if (TDS_FAILED(ret) || TDS_FAILED(tds_process_simple_query(mtds))) return false; if (dbname_mismatch) database = tds_dstr_cstr(&login->database); else database = mtds->conn->env.database; } // 7.0 // env database // database change message (with server name correct) // env language // language change message // env 0x3 charset ("iso_1") // env 0x5 lcid ("1033") // env 0x6 ("196609" ?? 0x30001) // loginack // env 0x4 packet size // done // // 7.1/7.2/7.3 // env database // database change message (with server name correct) // env 0x7 collation // env language // language change message // loginack // env 0x4 packet size // done tds->out_flag = TDS_REPLY; tds_env_change(tds, TDS_ENV_DATABASE, "master", database); sprintf(msg, "Changed database context to '%s'.", database); tds_send_msg(tds, 5701, 2, 0, msg, server, NULL, 1); if (!login->suppress_language) { tds_env_change(tds, TDS_ENV_LANG, NULL, "us_english"); tds_send_msg(tds, 5703, 1, 0, "Changed language setting to 'us_english'.", server, NULL, 1); } if (IS_TDS71_PLUS(tds->conn)) { tds_put_byte(tds, TDS_ENVCHANGE_TOKEN); tds_put_smallint(tds, 8); tds_put_byte(tds, TDS_ENV_SQLCOLLATION); tds_put_byte(tds, 5); tds_put_n(tds, tds->conn->collation, 5); tds_put_byte(tds, 0); } tds_send_login_ack(tds, mtds->conn->product_name); sprintf(block, "%d", tds->conn->env.block_size); tds_env_change(tds, TDS_ENV_PACKSIZE, block, block); /* tds_send_capabilities_token(tds); */ tds_send_done_token(tds, 0, 0); /* send it! */ tds_flush_packet(tds); tds_free_login(login); puser->login = NULL; return true; }