SqlConnectionString.cs 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  1. //------------------------------------------------------------------------------
  2. // <copyright file="SqlConnectionString.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. // <owner current="true" primary="true">[....]</owner>
  6. // <owner current="true" primary="false">[....]</owner>
  7. //------------------------------------------------------------------------------
  8. namespace System.Data.SqlClient {
  9. using System;
  10. using System.Collections;
  11. using System.Data;
  12. using System.Data.Common;
  13. using System.Diagnostics;
  14. using System.Globalization;
  15. using System.IO;
  16. using System.Security;
  17. using System.Security.Permissions;
  18. using System.Text;
  19. using System.Runtime.Versioning;
  20. internal sealed class SqlConnectionString : DbConnectionOptions {
  21. // instances of this class are intended to be immutable, i.e readonly
  22. // used by pooling classes so it is much easier to verify correctness
  23. // when not worried about the class being modified during execution
  24. internal static class DEFAULT {
  25. internal const ApplicationIntent ApplicationIntent = DbConnectionStringDefaults.ApplicationIntent;
  26. internal const string Application_Name = TdsEnums.SQL_PROVIDER_NAME;
  27. internal const bool Asynchronous = false;
  28. internal const string AttachDBFilename = "";
  29. internal const int Connect_Timeout = ADP.DefaultConnectionTimeout;
  30. internal const bool Connection_Reset = true;
  31. internal const bool Context_Connection = false;
  32. internal const string Current_Language = "";
  33. internal const string Data_Source = "";
  34. internal const bool Encrypt = false;
  35. internal const bool Enlist = true;
  36. internal const string FailoverPartner = "";
  37. internal const string Initial_Catalog = "";
  38. internal const bool Integrated_Security = false;
  39. internal const int Load_Balance_Timeout = 0; // default of 0 means don't use
  40. internal const bool MARS = false;
  41. internal const int Max_Pool_Size = 100;
  42. internal const int Min_Pool_Size = 0;
  43. internal const bool MultiSubnetFailover = DbConnectionStringDefaults.MultiSubnetFailover;
  44. internal const bool TransparentNetworkIPResolution = DbConnectionStringDefaults.TransparentNetworkIPResolution;
  45. internal const string Network_Library = "";
  46. internal const int Packet_Size = 8000;
  47. internal const string Password = "";
  48. internal const bool Persist_Security_Info = false;
  49. internal const bool Pooling = true;
  50. internal const bool TrustServerCertificate = false;
  51. internal const string Type_System_Version = "";
  52. internal const string User_ID = "";
  53. internal const bool User_Instance = false;
  54. internal const bool Replication = false;
  55. internal const int Connect_Retry_Count = 1;
  56. internal const int Connect_Retry_Interval = 10;
  57. internal static readonly SqlAuthenticationMethod Authentication = SqlAuthenticationMethod.NotSpecified;
  58. internal static readonly SqlConnectionColumnEncryptionSetting ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Disabled;
  59. }
  60. // SqlConnection ConnectionString Options
  61. // keys must be lowercase!
  62. internal static class KEY {
  63. internal const string ApplicationIntent = "applicationintent";
  64. internal const string Application_Name = "application name";
  65. internal const string AsynchronousProcessing = "asynchronous processing";
  66. internal const string AttachDBFilename = "attachdbfilename";
  67. internal const string ColumnEncryptionSetting = "column encryption setting";
  68. internal const string Connect_Timeout = "connect timeout";
  69. internal const string Connection_Reset = "connection reset";
  70. internal const string Context_Connection = "context connection";
  71. internal const string Current_Language = "current language";
  72. internal const string Data_Source = "data source";
  73. internal const string Encrypt = "encrypt";
  74. internal const string Enlist = "enlist";
  75. internal const string FailoverPartner = "failover partner";
  76. internal const string Initial_Catalog = "initial catalog";
  77. internal const string Integrated_Security = "integrated security";
  78. internal const string Load_Balance_Timeout = "load balance timeout";
  79. internal const string MARS = "multipleactiveresultsets";
  80. internal const string Max_Pool_Size = "max pool size";
  81. internal const string Min_Pool_Size = "min pool size";
  82. internal const string MultiSubnetFailover = "multisubnetfailover";
  83. internal const string TransparentNetworkIPResolution = "transparentnetworkipresolution";
  84. internal const string Network_Library = "network library";
  85. internal const string Packet_Size = "packet size";
  86. internal const string Password = "password";
  87. internal const string Persist_Security_Info = "persist security info";
  88. internal const string Pooling = "pooling";
  89. internal const string TransactionBinding = "transaction binding";
  90. internal const string TrustServerCertificate = "trustservercertificate";
  91. internal const string Type_System_Version = "type system version";
  92. internal const string User_ID = "user id";
  93. internal const string User_Instance = "user instance";
  94. internal const string Workstation_Id = "workstation id";
  95. internal const string Replication = "replication";
  96. internal const string Connect_Retry_Count = "connectretrycount";
  97. internal const string Connect_Retry_Interval = "connectretryinterval";
  98. internal const string Authentication = "authentication";
  99. }
  100. // Constant for the number of duplicate options in the connnection string
  101. private static class SYNONYM {
  102. // application name
  103. internal const string APP = "app";
  104. internal const string Async = "async";
  105. // attachDBFilename
  106. internal const string EXTENDED_PROPERTIES = "extended properties";
  107. internal const string INITIAL_FILE_NAME = "initial file name";
  108. // connect timeout
  109. internal const string CONNECTION_TIMEOUT = "connection timeout";
  110. internal const string TIMEOUT = "timeout";
  111. // current language
  112. internal const string LANGUAGE = "language";
  113. // data source
  114. internal const string ADDR = "addr";
  115. internal const string ADDRESS = "address";
  116. internal const string SERVER = "server";
  117. internal const string NETWORK_ADDRESS = "network address";
  118. // initial catalog
  119. internal const string DATABASE = "database";
  120. // integrated security
  121. internal const string TRUSTED_CONNECTION = "trusted_connection";
  122. // load balance timeout
  123. internal const string Connection_Lifetime = "connection lifetime";
  124. // network library
  125. internal const string NET = "net";
  126. internal const string NETWORK = "network";
  127. // password
  128. internal const string Pwd = "pwd";
  129. // persist security info
  130. internal const string PERSISTSECURITYINFO = "persistsecurityinfo";
  131. // user id
  132. internal const string UID = "uid";
  133. internal const string User = "user";
  134. // workstation id
  135. internal const string WSID = "wsid";
  136. // make sure to update SynonymCount value below when adding or removing synonyms
  137. }
  138. internal const int SynonymCount = 21;
  139. // the following are all inserted as keys into the _netlibMapping hash
  140. internal static class NETLIB {
  141. internal const string AppleTalk = "dbmsadsn";
  142. internal const string BanyanVines = "dbmsvinn";
  143. internal const string IPXSPX = "dbmsspxn";
  144. internal const string Multiprotocol = "dbmsrpcn";
  145. internal const string NamedPipes = "dbnmpntw";
  146. internal const string SharedMemory = "dbmslpcn";
  147. internal const string TCPIP = "dbmssocn";
  148. internal const string VIA = "dbmsgnet";
  149. }
  150. internal enum TypeSystem {
  151. Latest = 2008,
  152. SQLServer2000 = 2000,
  153. SQLServer2005 = 2005,
  154. SQLServer2008 = 2008,
  155. SQLServer2012 = 2012,
  156. }
  157. internal static class TYPESYSTEMVERSION {
  158. internal const string Latest = "Latest";
  159. internal const string SQL_Server_2000 = "SQL Server 2000";
  160. internal const string SQL_Server_2005 = "SQL Server 2005";
  161. internal const string SQL_Server_2008 = "SQL Server 2008";
  162. internal const string SQL_Server_2012 = "SQL Server 2012";
  163. }
  164. internal enum TransactionBindingEnum {
  165. ImplicitUnbind,
  166. ExplicitUnbind
  167. }
  168. internal static class TRANSACIONBINDING {
  169. internal const string ImplicitUnbind = "Implicit Unbind";
  170. internal const string ExplicitUnbind = "Explicit Unbind";
  171. }
  172. static private Hashtable _sqlClientSynonyms;
  173. static private Hashtable _netlibMapping;
  174. private readonly bool _integratedSecurity;
  175. private readonly bool _connectionReset;
  176. private readonly bool _contextConnection;
  177. private readonly bool _encrypt;
  178. private readonly bool _trustServerCertificate;
  179. private readonly bool _enlist;
  180. private readonly bool _mars;
  181. private readonly bool _persistSecurityInfo;
  182. private readonly bool _pooling;
  183. private readonly bool _replication;
  184. private readonly bool _userInstance;
  185. private readonly bool _multiSubnetFailover;
  186. private readonly bool _transparentNetworkIPResolution;
  187. private readonly SqlAuthenticationMethod _authType;
  188. private readonly SqlConnectionColumnEncryptionSetting _columnEncryptionSetting;
  189. private readonly int _connectTimeout;
  190. private readonly int _loadBalanceTimeout;
  191. private readonly int _maxPoolSize;
  192. private readonly int _minPoolSize;
  193. private readonly int _packetSize;
  194. private readonly int _connectRetryCount;
  195. private readonly int _connectRetryInterval;
  196. private readonly ApplicationIntent _applicationIntent;
  197. private readonly string _applicationName;
  198. private readonly string _attachDBFileName;
  199. private readonly string _currentLanguage;
  200. private readonly string _dataSource;
  201. private readonly string _localDBInstance; // created based on datasource, set to NULL if datasource is not LocalDB
  202. private readonly string _failoverPartner;
  203. private readonly string _initialCatalog;
  204. private readonly string _password;
  205. private readonly string _userID;
  206. private readonly string _networkLibrary;
  207. private readonly string _workstationId;
  208. private readonly TypeSystem _typeSystemVersion;
  209. private readonly Version _typeSystemAssemblyVersion;
  210. private static readonly Version constTypeSystemAsmVersion10 = new Version("10.0.0.0");
  211. private static readonly Version constTypeSystemAsmVersion11 = new Version("11.0.0.0");
  212. private readonly TransactionBindingEnum _transactionBinding;
  213. private readonly string _expandedAttachDBFilename; // expanded during construction so that CreatePermissionSet & Expand are consistent
  214. // SxS: reading Software\\Microsoft\\MSSQLServer\\Client\\SuperSocketNetLib\Encrypt value from registry
  215. [ResourceExposure(ResourceScope.None)]
  216. [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  217. internal SqlConnectionString(string connectionString) : base(connectionString, GetParseSynonyms(), false) {
  218. bool runningInProc = InOutOfProcHelper.InProc;
  219. _integratedSecurity = ConvertValueToIntegratedSecurity();
  220. ConvertValueToBoolean(KEY.AsynchronousProcessing, DEFAULT.Asynchronous); // while we don't use it anymore, we still need to verify it is true/false
  221. // SQLPT 41700: Ignore ResetConnection=False (still validate the keyword/value)
  222. _connectionReset = ConvertValueToBoolean(KEY.Connection_Reset, DEFAULT.Connection_Reset);
  223. _contextConnection = ConvertValueToBoolean(KEY.Context_Connection, DEFAULT.Context_Connection);
  224. _encrypt = ConvertValueToEncrypt();
  225. _enlist = ConvertValueToBoolean(KEY.Enlist, ADP.IsWindowsNT);
  226. _mars = ConvertValueToBoolean(KEY.MARS, DEFAULT.MARS);
  227. _persistSecurityInfo = ConvertValueToBoolean(KEY.Persist_Security_Info, DEFAULT.Persist_Security_Info);
  228. _pooling = ConvertValueToBoolean(KEY.Pooling, DEFAULT.Pooling);
  229. _replication = ConvertValueToBoolean(KEY.Replication, DEFAULT.Replication);
  230. _userInstance = ConvertValueToBoolean(KEY.User_Instance, DEFAULT.User_Instance);
  231. _multiSubnetFailover = ConvertValueToBoolean(KEY.MultiSubnetFailover, DEFAULT.MultiSubnetFailover);
  232. _transparentNetworkIPResolution = ConvertValueToBoolean(KEY.TransparentNetworkIPResolution, DEFAULT.TransparentNetworkIPResolution);
  233. _connectTimeout = ConvertValueToInt32(KEY.Connect_Timeout, DEFAULT.Connect_Timeout);
  234. _loadBalanceTimeout = ConvertValueToInt32(KEY.Load_Balance_Timeout, DEFAULT.Load_Balance_Timeout);
  235. _maxPoolSize = ConvertValueToInt32(KEY.Max_Pool_Size, DEFAULT.Max_Pool_Size);
  236. _minPoolSize = ConvertValueToInt32(KEY.Min_Pool_Size, DEFAULT.Min_Pool_Size);
  237. _packetSize = ConvertValueToInt32(KEY.Packet_Size, DEFAULT.Packet_Size);
  238. _connectRetryCount = ConvertValueToInt32(KEY.Connect_Retry_Count, DEFAULT.Connect_Retry_Count);
  239. _connectRetryInterval = ConvertValueToInt32(KEY.Connect_Retry_Interval, DEFAULT.Connect_Retry_Interval);
  240. _applicationIntent = ConvertValueToApplicationIntent();
  241. _applicationName = ConvertValueToString(KEY.Application_Name, DEFAULT.Application_Name);
  242. _attachDBFileName = ConvertValueToString(KEY.AttachDBFilename, DEFAULT.AttachDBFilename);
  243. _currentLanguage = ConvertValueToString(KEY.Current_Language, DEFAULT.Current_Language);
  244. _dataSource = ConvertValueToString(KEY.Data_Source, DEFAULT.Data_Source);
  245. _localDBInstance = LocalDBAPI.GetLocalDbInstanceNameFromServerName(_dataSource);
  246. _failoverPartner = ConvertValueToString(KEY.FailoverPartner, DEFAULT.FailoverPartner);
  247. _initialCatalog = ConvertValueToString(KEY.Initial_Catalog, DEFAULT.Initial_Catalog);
  248. _networkLibrary = ConvertValueToString(KEY.Network_Library, null);
  249. _password = ConvertValueToString(KEY.Password, DEFAULT.Password);
  250. _trustServerCertificate = ConvertValueToBoolean(KEY.TrustServerCertificate, DEFAULT.TrustServerCertificate);
  251. _authType = ConvertValueToAuthenticationType();
  252. _columnEncryptionSetting = ConvertValueToColumnEncryptionSetting();
  253. // Temporary string - this value is stored internally as an enum.
  254. string typeSystemVersionString = ConvertValueToString(KEY.Type_System_Version, null);
  255. string transactionBindingString = ConvertValueToString(KEY.TransactionBinding, null);
  256. _userID = ConvertValueToString(KEY.User_ID, DEFAULT.User_ID);
  257. _workstationId = ConvertValueToString(KEY.Workstation_Id, null);
  258. if (_contextConnection) {
  259. // We have to be running in the engine for you to request a
  260. // context connection.
  261. if (!runningInProc) {
  262. throw SQL.ContextUnavailableOutOfProc();
  263. }
  264. // When using a context connection, we need to ensure that no
  265. // other connection string keywords are specified.
  266. foreach (DictionaryEntry entry in Parsetable) {
  267. if ((string) entry.Key != KEY.Context_Connection &&
  268. (string) entry.Key != KEY.Type_System_Version) {
  269. throw SQL.ContextAllowsLimitedKeywords();
  270. }
  271. }
  272. }
  273. if (!_encrypt) { // Support legacy registry encryption settings
  274. const string folder = "Software\\Microsoft\\MSSQLServer\\Client\\SuperSocketNetLib";
  275. const string value = "Encrypt";
  276. Object obj = ADP.LocalMachineRegistryValue(folder, value);
  277. if ((obj is Int32) && (1 == (int)obj)) { // If the registry key exists
  278. _encrypt = true;
  279. }
  280. }
  281. if (_loadBalanceTimeout < 0) {
  282. throw ADP.InvalidConnectionOptionValue(KEY.Load_Balance_Timeout);
  283. }
  284. if (_connectTimeout < 0) {
  285. throw ADP.InvalidConnectionOptionValue(KEY.Connect_Timeout);
  286. }
  287. if (_maxPoolSize < 1) {
  288. throw ADP.InvalidConnectionOptionValue(KEY.Max_Pool_Size);
  289. }
  290. if (_minPoolSize < 0) {
  291. throw ADP.InvalidConnectionOptionValue(KEY.Min_Pool_Size);
  292. }
  293. if (_maxPoolSize < _minPoolSize) {
  294. throw ADP.InvalidMinMaxPoolSizeValues();
  295. }
  296. if ((_packetSize < TdsEnums.MIN_PACKET_SIZE) || (TdsEnums.MAX_PACKET_SIZE < _packetSize)) {
  297. throw SQL.InvalidPacketSizeValue();
  298. }
  299. if (null != _networkLibrary) { // MDAC 83525
  300. string networkLibrary = _networkLibrary.Trim().ToLower(CultureInfo.InvariantCulture);
  301. Hashtable netlib = NetlibMapping();
  302. if (!netlib.ContainsKey(networkLibrary)) {
  303. throw ADP.InvalidConnectionOptionValue(KEY.Network_Library);
  304. }
  305. _networkLibrary = (string) netlib[networkLibrary];
  306. }
  307. else {
  308. _networkLibrary = DEFAULT.Network_Library;
  309. }
  310. ValidateValueLength(_applicationName, TdsEnums.MAXLEN_APPNAME, KEY.Application_Name);
  311. ValidateValueLength(_currentLanguage , TdsEnums.MAXLEN_LANGUAGE, KEY.Current_Language);
  312. ValidateValueLength(_dataSource, TdsEnums.MAXLEN_SERVERNAME, KEY.Data_Source);
  313. ValidateValueLength(_failoverPartner, TdsEnums.MAXLEN_SERVERNAME, KEY.FailoverPartner);
  314. ValidateValueLength(_initialCatalog, TdsEnums.MAXLEN_DATABASE, KEY.Initial_Catalog);
  315. ValidateValueLength(_password, TdsEnums.MAXLEN_PASSWORD, KEY.Password);
  316. ValidateValueLength(_userID, TdsEnums.MAXLEN_USERNAME, KEY.User_ID);
  317. if (null != _workstationId) {
  318. ValidateValueLength(_workstationId, TdsEnums.MAXLEN_HOSTNAME, KEY.Workstation_Id);
  319. }
  320. if (!String.Equals(DEFAULT.FailoverPartner, _failoverPartner, StringComparison.OrdinalIgnoreCase)) {
  321. // fail-over partner is set
  322. if (_multiSubnetFailover) {
  323. throw SQL.MultiSubnetFailoverWithFailoverPartner(serverProvidedFailoverPartner: false, internalConnection: null);
  324. }
  325. if (String.Equals(DEFAULT.Initial_Catalog, _initialCatalog, StringComparison.OrdinalIgnoreCase)) {
  326. throw ADP.MissingConnectionOptionValue(KEY.FailoverPartner, KEY.Initial_Catalog);
  327. }
  328. }
  329. // expand during construction so that CreatePermissionSet and Expand are consistent
  330. string datadir = null;
  331. _expandedAttachDBFilename = ExpandDataDirectory(KEY.AttachDBFilename, _attachDBFileName, ref datadir);
  332. if (null != _expandedAttachDBFilename) {
  333. if (0 <= _expandedAttachDBFilename.IndexOf('|')) {
  334. throw ADP.InvalidConnectionOptionValue(KEY.AttachDBFilename);
  335. }
  336. ValidateValueLength(_expandedAttachDBFilename, TdsEnums.MAXLEN_ATTACHDBFILE, KEY.AttachDBFilename);
  337. if (_localDBInstance == null)
  338. {
  339. // fail fast to verify LocalHost when using |DataDirectory|
  340. // still must check again at connect time
  341. string host = _dataSource;
  342. string protocol = _networkLibrary;
  343. TdsParserStaticMethods.AliasRegistryLookup(ref host, ref protocol);
  344. VerifyLocalHostAndFixup(ref host, true, false /*don't fix-up*/);
  345. }
  346. }
  347. else if (0 <= _attachDBFileName.IndexOf('|')) {
  348. throw ADP.InvalidConnectionOptionValue(KEY.AttachDBFilename);
  349. }
  350. else {
  351. ValidateValueLength(_attachDBFileName, TdsEnums.MAXLEN_ATTACHDBFILE, KEY.AttachDBFilename);
  352. }
  353. _typeSystemAssemblyVersion = constTypeSystemAsmVersion10;
  354. if (true == _userInstance && !ADP.IsEmpty(_failoverPartner)) {
  355. throw SQL.UserInstanceFailoverNotCompatible();
  356. }
  357. if (ADP.IsEmpty(typeSystemVersionString)) {
  358. typeSystemVersionString = DbConnectionStringDefaults.TypeSystemVersion;
  359. }
  360. if (typeSystemVersionString.Equals(TYPESYSTEMVERSION.Latest, StringComparison.OrdinalIgnoreCase)) {
  361. _typeSystemVersion = TypeSystem.Latest;
  362. }
  363. else if (typeSystemVersionString.Equals(TYPESYSTEMVERSION.SQL_Server_2000, StringComparison.OrdinalIgnoreCase)) {
  364. if (_contextConnection) {
  365. throw SQL.ContextAllowsOnlyTypeSystem2005();
  366. }
  367. _typeSystemVersion = TypeSystem.SQLServer2000;
  368. }
  369. else if (typeSystemVersionString.Equals(TYPESYSTEMVERSION.SQL_Server_2005, StringComparison.OrdinalIgnoreCase)) {
  370. _typeSystemVersion = TypeSystem.SQLServer2005;
  371. }
  372. else if (typeSystemVersionString.Equals(TYPESYSTEMVERSION.SQL_Server_2008, StringComparison.OrdinalIgnoreCase)) {
  373. _typeSystemVersion = TypeSystem.SQLServer2008;
  374. }
  375. else if (typeSystemVersionString.Equals(TYPESYSTEMVERSION.SQL_Server_2012, StringComparison.OrdinalIgnoreCase)) {
  376. _typeSystemVersion = TypeSystem.SQLServer2012;
  377. _typeSystemAssemblyVersion = constTypeSystemAsmVersion11;
  378. }
  379. else {
  380. throw ADP.InvalidConnectionOptionValue(KEY.Type_System_Version);
  381. }
  382. if (ADP.IsEmpty(transactionBindingString)) {
  383. transactionBindingString = DbConnectionStringDefaults.TransactionBinding;
  384. }
  385. if (transactionBindingString.Equals(TRANSACIONBINDING.ImplicitUnbind, StringComparison.OrdinalIgnoreCase)) {
  386. _transactionBinding = TransactionBindingEnum.ImplicitUnbind;
  387. }
  388. else if (transactionBindingString.Equals(TRANSACIONBINDING.ExplicitUnbind, StringComparison.OrdinalIgnoreCase)) {
  389. _transactionBinding = TransactionBindingEnum.ExplicitUnbind;
  390. }
  391. else {
  392. throw ADP.InvalidConnectionOptionValue(KEY.TransactionBinding);
  393. }
  394. if (_applicationIntent == ApplicationIntent.ReadOnly && !String.IsNullOrEmpty(_failoverPartner))
  395. throw SQL.ROR_FailoverNotSupportedConnString();
  396. if ((_connectRetryCount<0) || (_connectRetryCount>255)) {
  397. throw ADP.InvalidConnectRetryCountValue();
  398. }
  399. if ((_connectRetryInterval < 1) || (_connectRetryInterval > 60)) {
  400. throw ADP.InvalidConnectRetryIntervalValue();
  401. }
  402. if (Authentication != SqlAuthenticationMethod.NotSpecified && _integratedSecurity == true) {
  403. throw SQL.AuthenticationAndIntegratedSecurity();
  404. }
  405. if (Authentication == SqlClient.SqlAuthenticationMethod.ActiveDirectoryIntegrated && (HasUserIdKeyword || HasPasswordKeyword)) {
  406. throw SQL.IntegratedWithUserIDAndPassword();
  407. }
  408. }
  409. // This c-tor is used to create SSE and user instance connection strings when user instance is set to true
  410. //
  411. internal SqlConnectionString(SqlConnectionString connectionOptions, string dataSource, bool userInstance, bool? setEnlistValue) : base(connectionOptions) {
  412. _integratedSecurity = connectionOptions._integratedSecurity;
  413. _connectionReset = connectionOptions._connectionReset;
  414. _contextConnection = connectionOptions._contextConnection;
  415. _encrypt = connectionOptions._encrypt;
  416. if (setEnlistValue.HasValue) {
  417. _enlist = setEnlistValue.Value;
  418. }
  419. else {
  420. _enlist = connectionOptions._enlist;
  421. }
  422. _mars = connectionOptions._mars;
  423. _persistSecurityInfo = connectionOptions._persistSecurityInfo;
  424. _pooling = connectionOptions._pooling;
  425. _replication = connectionOptions._replication;
  426. _userInstance = userInstance;
  427. _connectTimeout = connectionOptions._connectTimeout;
  428. _loadBalanceTimeout = connectionOptions._loadBalanceTimeout;
  429. _maxPoolSize = connectionOptions._maxPoolSize;
  430. _minPoolSize = connectionOptions._minPoolSize;
  431. _multiSubnetFailover = connectionOptions._multiSubnetFailover;
  432. _transparentNetworkIPResolution = connectionOptions._transparentNetworkIPResolution;
  433. _packetSize = connectionOptions._packetSize;
  434. _applicationName = connectionOptions._applicationName;
  435. _attachDBFileName = connectionOptions._attachDBFileName;
  436. _currentLanguage = connectionOptions._currentLanguage;
  437. _dataSource = dataSource;
  438. _localDBInstance = LocalDBAPI.GetLocalDbInstanceNameFromServerName(_dataSource);
  439. _failoverPartner = connectionOptions._failoverPartner;
  440. _initialCatalog = connectionOptions._initialCatalog;
  441. _password = connectionOptions._password;
  442. _userID = connectionOptions._userID;
  443. _networkLibrary = connectionOptions._networkLibrary;
  444. _workstationId = connectionOptions._workstationId;
  445. _expandedAttachDBFilename = connectionOptions._expandedAttachDBFilename;
  446. _typeSystemVersion = connectionOptions._typeSystemVersion;
  447. _typeSystemAssemblyVersion = connectionOptions._typeSystemAssemblyVersion;
  448. _transactionBinding = connectionOptions._transactionBinding;
  449. _applicationIntent = connectionOptions._applicationIntent;
  450. _connectRetryCount = connectionOptions._connectRetryCount;
  451. _connectRetryInterval = connectionOptions._connectRetryInterval;
  452. _authType = connectionOptions._authType;
  453. _columnEncryptionSetting = connectionOptions._columnEncryptionSetting;
  454. ValidateValueLength(_dataSource, TdsEnums.MAXLEN_SERVERNAME, KEY.Data_Source);
  455. }
  456. internal bool IntegratedSecurity { get { return _integratedSecurity; } }
  457. // We always initialize in Async mode so that both synchronous and asynchronous methods
  458. // will work. In the future we can deprecate the keyword entirely.
  459. internal bool Asynchronous { get { return true; } }
  460. // SQLPT 41700: Ignore ResetConnection=False, always reset the connection for security
  461. internal bool ConnectionReset { get { return true; } }
  462. internal bool ContextConnection { get { return _contextConnection; } }
  463. // internal bool EnableUdtDownload { get { return _enableUdtDownload;} }
  464. internal bool Encrypt { get { return _encrypt; } }
  465. internal bool TrustServerCertificate { get { return _trustServerCertificate; } }
  466. internal bool Enlist { get { return _enlist; } }
  467. internal bool MARS { get { return _mars; } }
  468. internal bool MultiSubnetFailover { get { return _multiSubnetFailover; } }
  469. internal bool TransparentNetworkIPResolution { get { return _transparentNetworkIPResolution; } }
  470. internal SqlAuthenticationMethod Authentication { get { return _authType; } }
  471. internal SqlConnectionColumnEncryptionSetting ColumnEncryptionSetting { get { return _columnEncryptionSetting; } }
  472. internal bool PersistSecurityInfo { get { return _persistSecurityInfo; } }
  473. internal bool Pooling { get { return _pooling; } }
  474. internal bool Replication { get { return _replication; } }
  475. internal bool UserInstance { get { return _userInstance; } }
  476. internal int ConnectTimeout { get { return _connectTimeout; } }
  477. internal int LoadBalanceTimeout { get { return _loadBalanceTimeout; } }
  478. internal int MaxPoolSize { get { return _maxPoolSize; } }
  479. internal int MinPoolSize { get { return _minPoolSize; } }
  480. internal int PacketSize { get { return _packetSize; } }
  481. internal int ConnectRetryCount { get { return _connectRetryCount; } }
  482. internal int ConnectRetryInterval { get { return _connectRetryInterval; } }
  483. internal ApplicationIntent ApplicationIntent { get { return _applicationIntent; } }
  484. internal string ApplicationName { get { return _applicationName; } }
  485. internal string AttachDBFilename { get { return _attachDBFileName; } }
  486. internal string CurrentLanguage { get { return _currentLanguage; } }
  487. internal string DataSource { get { return _dataSource; } }
  488. internal string LocalDBInstance { get { return _localDBInstance; } }
  489. internal string FailoverPartner { get { return _failoverPartner; } }
  490. internal string InitialCatalog { get { return _initialCatalog; } }
  491. internal string NetworkLibrary { get { return _networkLibrary; } }
  492. internal string Password { get { return _password; } }
  493. internal string UserID { get { return _userID; } }
  494. internal string WorkstationId { get { return _workstationId; } }
  495. internal TypeSystem TypeSystemVersion { get { return _typeSystemVersion; } }
  496. internal Version TypeSystemAssemblyVersion { get { return _typeSystemAssemblyVersion; } }
  497. internal TransactionBindingEnum TransactionBinding { get { return _transactionBinding; } }
  498. internal bool EnforceLocalHost {
  499. get {
  500. // so tdsparser.connect can determine if SqlConnection.UserConnectionOptions
  501. // needs to enfoce local host after datasource alias lookup
  502. return (null != _expandedAttachDBFilename) && (null == _localDBInstance);
  503. }
  504. }
  505. protected internal override System.Security.PermissionSet CreatePermissionSet() {
  506. System.Security.PermissionSet permissionSet = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
  507. permissionSet.AddPermission(new SqlClientPermission(this));
  508. return permissionSet;
  509. }
  510. protected internal override string Expand() {
  511. if (null != _expandedAttachDBFilename) {
  512. return ExpandKeyword(KEY.AttachDBFilename, _expandedAttachDBFilename);
  513. }
  514. else {
  515. return base.Expand();
  516. }
  517. }
  518. private static bool CompareHostName(ref string host, string name, bool fixup) {
  519. // same computer name or same computer name + "\named instance"
  520. bool equal = false;
  521. if (host.Equals(name, StringComparison.OrdinalIgnoreCase)) {
  522. if (fixup) {
  523. host = ".";
  524. }
  525. equal = true;
  526. }
  527. else if (host.StartsWith(name+@"\", StringComparison.OrdinalIgnoreCase)) {
  528. if (fixup) {
  529. host = "." + host.Substring(name.Length);
  530. }
  531. equal = true;
  532. }
  533. return equal;
  534. }
  535. // this hashtable is meant to be read-only translation of parsed string
  536. // keywords/synonyms to a known keyword string
  537. internal static Hashtable GetParseSynonyms() {
  538. Hashtable hash = _sqlClientSynonyms;
  539. if (null == hash) {
  540. hash = new Hashtable(SqlConnectionStringBuilder.KeywordsCount + SynonymCount);
  541. hash.Add(KEY.ApplicationIntent, KEY.ApplicationIntent);
  542. hash.Add(KEY.Application_Name, KEY.Application_Name);
  543. hash.Add(KEY.AsynchronousProcessing, KEY.AsynchronousProcessing);
  544. hash.Add(KEY.AttachDBFilename, KEY.AttachDBFilename);
  545. hash.Add(KEY.Connect_Timeout, KEY.Connect_Timeout);
  546. hash.Add(KEY.Connection_Reset, KEY.Connection_Reset);
  547. hash.Add(KEY.Context_Connection, KEY.Context_Connection);
  548. hash.Add(KEY.Current_Language, KEY.Current_Language);
  549. hash.Add(KEY.Data_Source, KEY.Data_Source);
  550. hash.Add(KEY.Encrypt, KEY.Encrypt);
  551. hash.Add(KEY.Enlist, KEY.Enlist);
  552. hash.Add(KEY.FailoverPartner, KEY.FailoverPartner);
  553. hash.Add(KEY.Initial_Catalog, KEY.Initial_Catalog);
  554. hash.Add(KEY.Integrated_Security, KEY.Integrated_Security);
  555. hash.Add(KEY.Load_Balance_Timeout, KEY.Load_Balance_Timeout);
  556. hash.Add(KEY.MARS, KEY.MARS);
  557. hash.Add(KEY.Max_Pool_Size, KEY.Max_Pool_Size);
  558. hash.Add(KEY.Min_Pool_Size, KEY.Min_Pool_Size);
  559. hash.Add(KEY.MultiSubnetFailover, KEY.MultiSubnetFailover);
  560. hash.Add(KEY.TransparentNetworkIPResolution, KEY.TransparentNetworkIPResolution);
  561. hash.Add(KEY.Network_Library, KEY.Network_Library);
  562. hash.Add(KEY.Packet_Size, KEY.Packet_Size);
  563. hash.Add(KEY.Password, KEY.Password);
  564. hash.Add(KEY.Persist_Security_Info, KEY.Persist_Security_Info);
  565. hash.Add(KEY.Pooling, KEY.Pooling);
  566. hash.Add(KEY.Replication, KEY.Replication);
  567. hash.Add(KEY.TrustServerCertificate, KEY.TrustServerCertificate);
  568. hash.Add(KEY.TransactionBinding, KEY.TransactionBinding);
  569. hash.Add(KEY.Type_System_Version, KEY.Type_System_Version);
  570. hash.Add(KEY.ColumnEncryptionSetting, KEY.ColumnEncryptionSetting);
  571. hash.Add(KEY.User_ID, KEY.User_ID);
  572. hash.Add(KEY.User_Instance, KEY.User_Instance);
  573. hash.Add(KEY.Workstation_Id, KEY.Workstation_Id);
  574. hash.Add(KEY.Connect_Retry_Count, KEY.Connect_Retry_Count);
  575. hash.Add(KEY.Connect_Retry_Interval, KEY.Connect_Retry_Interval);
  576. hash.Add(KEY.Authentication, KEY.Authentication);
  577. hash.Add(SYNONYM.APP, KEY.Application_Name);
  578. hash.Add(SYNONYM.Async, KEY.AsynchronousProcessing);
  579. hash.Add(SYNONYM.EXTENDED_PROPERTIES, KEY.AttachDBFilename);
  580. hash.Add(SYNONYM.INITIAL_FILE_NAME, KEY.AttachDBFilename);
  581. hash.Add(SYNONYM.CONNECTION_TIMEOUT, KEY.Connect_Timeout);
  582. hash.Add(SYNONYM.TIMEOUT, KEY.Connect_Timeout);
  583. hash.Add(SYNONYM.LANGUAGE, KEY.Current_Language);
  584. hash.Add(SYNONYM.ADDR, KEY.Data_Source);
  585. hash.Add(SYNONYM.ADDRESS, KEY.Data_Source);
  586. hash.Add(SYNONYM.NETWORK_ADDRESS, KEY.Data_Source);
  587. hash.Add(SYNONYM.SERVER, KEY.Data_Source);
  588. hash.Add(SYNONYM.DATABASE, KEY.Initial_Catalog);
  589. hash.Add(SYNONYM.TRUSTED_CONNECTION, KEY.Integrated_Security);
  590. hash.Add(SYNONYM.Connection_Lifetime, KEY.Load_Balance_Timeout);
  591. hash.Add(SYNONYM.NET, KEY.Network_Library);
  592. hash.Add(SYNONYM.NETWORK, KEY.Network_Library);
  593. hash.Add(SYNONYM.Pwd, KEY.Password);
  594. hash.Add(SYNONYM.PERSISTSECURITYINFO, KEY.Persist_Security_Info);
  595. hash.Add(SYNONYM.UID, KEY.User_ID);
  596. hash.Add(SYNONYM.User, KEY.User_ID);
  597. hash.Add(SYNONYM.WSID, KEY.Workstation_Id);
  598. Debug.Assert(SqlConnectionStringBuilder.KeywordsCount + SynonymCount == hash.Count, "incorrect initial ParseSynonyms size");
  599. _sqlClientSynonyms = hash;
  600. }
  601. return hash;
  602. }
  603. internal string ObtainWorkstationId() {
  604. // If not supplied by the user, the default value is the MachineName
  605. // Note: In Longhorn you'll be able to rename a machine without
  606. // rebooting. Therefore, don't cache this machine name.
  607. string result = WorkstationId;
  608. if (null == result) {
  609. // permission to obtain Environment.MachineName is Asserted
  610. // since permission to open the connection has been granted
  611. // the information is shared with the server, but not directly with the user
  612. result = ADP.MachineName();
  613. ValidateValueLength(result, TdsEnums.MAXLEN_HOSTNAME, KEY.Workstation_Id);
  614. }
  615. return result;
  616. }
  617. static internal Hashtable NetlibMapping() {
  618. const int NetLibCount = 8;
  619. Hashtable hash = _netlibMapping;
  620. if (null == hash) {
  621. hash = new Hashtable(NetLibCount);
  622. hash.Add(NETLIB.TCPIP, TdsEnums.TCP);
  623. hash.Add(NETLIB.NamedPipes, TdsEnums.NP);
  624. hash.Add(NETLIB.Multiprotocol, TdsEnums.RPC);
  625. hash.Add(NETLIB.BanyanVines, TdsEnums.BV);
  626. hash.Add(NETLIB.AppleTalk, TdsEnums.ADSP);
  627. hash.Add(NETLIB.IPXSPX, TdsEnums.SPX);
  628. hash.Add(NETLIB.VIA, TdsEnums.VIA);
  629. hash.Add(NETLIB.SharedMemory, TdsEnums.LPC);
  630. Debug.Assert(NetLibCount == hash.Count, "incorrect initial NetlibMapping size");
  631. _netlibMapping = hash;
  632. }
  633. return hash;
  634. }
  635. static internal bool ValidProtocal (string protocal) {
  636. switch (protocal) {
  637. case TdsEnums.TCP :
  638. case TdsEnums.NP :
  639. case TdsEnums.VIA :
  640. case TdsEnums.LPC :
  641. return true;
  642. // case TdsEnums.RPC : Invalid Protocals
  643. // case TdsEnums.BV :
  644. // case TdsEnums.ADSP :
  645. // case TdsEnums.SPX :
  646. default :
  647. return false;
  648. }
  649. }
  650. private void ValidateValueLength (string value, int limit, string key) {
  651. if (limit < value.Length) {
  652. throw ADP.InvalidConnectionOptionValueLength(key, limit);
  653. }
  654. }
  655. internal static void VerifyLocalHostAndFixup(ref string host, bool enforceLocalHost, bool fixup) {
  656. if (ADP.IsEmpty(host)) {
  657. if (fixup) {
  658. host = ".";
  659. }
  660. }
  661. else if (!CompareHostName(ref host, @".", fixup) &&
  662. !CompareHostName(ref host, @"(local)", fixup)) {
  663. // Fix-up completed in CompareHostName if return value true.
  664. string name = ADP.GetComputerNameDnsFullyQualified(); // i.e, machine.location.corp.company.com
  665. if (!CompareHostName(ref host, name, fixup)) {
  666. int separatorPos = name.IndexOf('.'); // to compare just 'machine' part
  667. if ((separatorPos <= 0) || !CompareHostName(ref host, name.Substring(0, separatorPos), fixup)) {
  668. if (enforceLocalHost) {
  669. throw ADP.InvalidConnectionOptionValue(KEY.AttachDBFilename);
  670. }
  671. }
  672. }
  673. }
  674. }
  675. internal System.Data.SqlClient.ApplicationIntent ConvertValueToApplicationIntent() {
  676. object value = base.Parsetable[KEY.ApplicationIntent];
  677. if (value == null) {
  678. return DEFAULT.ApplicationIntent;
  679. }
  680. // when wrong value is used in the connection string provided to SqlConnection.ConnectionString or c-tor,
  681. // wrap Format and Overflow exceptions with Argument one, to be consistent with rest of the keyword types (like int and bool)
  682. try {
  683. return DbConnectionStringBuilderUtil.ConvertToApplicationIntent(KEY.ApplicationIntent, value);
  684. }
  685. catch (FormatException e) {
  686. throw ADP.InvalidConnectionOptionValue(KEY.ApplicationIntent, e);
  687. }
  688. catch (OverflowException e) {
  689. throw ADP.InvalidConnectionOptionValue(KEY.ApplicationIntent, e);
  690. }
  691. // ArgumentException and other types are raised as is (no wrapping)
  692. }
  693. internal SqlAuthenticationMethod ConvertValueToAuthenticationType() {
  694. object value = base.Parsetable[KEY.Authentication];
  695. string valStr = value as string;
  696. if (valStr == null) {
  697. return DEFAULT.Authentication;
  698. }
  699. try {
  700. return DbConnectionStringBuilderUtil.ConvertToAuthenticationType(KEY.Authentication, valStr);
  701. }
  702. catch (FormatException e) {
  703. throw ADP.InvalidConnectionOptionValue(KEY.Authentication, e);
  704. }
  705. catch (OverflowException e) {
  706. throw ADP.InvalidConnectionOptionValue(KEY.Authentication, e);
  707. }
  708. }
  709. /// <summary>
  710. /// Convert the value to SqlConnectionColumnEncryptionSetting.
  711. /// </summary>
  712. /// <returns></returns>
  713. internal SqlConnectionColumnEncryptionSetting ConvertValueToColumnEncryptionSetting() {
  714. object value = base.Parsetable[KEY.ColumnEncryptionSetting];
  715. string valStr = value as string;
  716. if (valStr == null) {
  717. return DEFAULT.ColumnEncryptionSetting;
  718. }
  719. try {
  720. return DbConnectionStringBuilderUtil.ConvertToColumnEncryptionSetting(KEY.ColumnEncryptionSetting, valStr);
  721. }
  722. catch (FormatException e) {
  723. throw ADP.InvalidConnectionOptionValue(KEY.ColumnEncryptionSetting, e);
  724. }
  725. catch (OverflowException e) {
  726. throw ADP.InvalidConnectionOptionValue(KEY.ColumnEncryptionSetting, e);
  727. }
  728. }
  729. internal bool ConvertValueToEncrypt() {
  730. // If the Authentication keyword is provided, default to Encrypt=true;
  731. // otherwise keep old default for backwards compatibility
  732. object authValue = base.Parsetable[KEY.Authentication];
  733. bool defaultEncryptValue = (authValue == null) ? DEFAULT.Encrypt : true;
  734. return ConvertValueToBoolean(KEY.Encrypt, defaultEncryptValue);
  735. }
  736. }
  737. }