1 /* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 #include <my_global.h>
24 #include <mysql.h>
25 #include <mysqld_error.h>
26 #include <my_thread.h>
27 #include <my_sys.h>
28 #include <mysys_err.h>
29 #include <m_string.h>
30 #include <m_ctype.h>
31 #include "errmsg.h"
32 #include <violite.h>
33 #include <sys/stat.h>
34 #include <signal.h>
35 #include <time.h>
36 #include <sql_common.h>
37 #include "embedded_priv.h"
38 #include "client_settings.h"
39 #ifdef	 HAVE_PWD_H
40 #include <pwd.h>
41 #endif
42 #ifdef HAVE_SYS_SELECT_H
43 #include <sys/select.h>
44 #endif
45 #ifdef HAVE_SYS_UN_H
46 #  include <sys/un.h>
47 #endif
48 #ifndef INADDR_NONE
49 #define INADDR_NONE	-1
50 #endif
51 
52 ulong net_buffer_length;
53 ulong max_allowed_packet;
54 
55 #if defined(_WIN32)
56 #define ERRNO WSAGetLastError()
57 #define perror(A)
58 #else
59 #include <errno.h>
60 #define ERRNO errno
61 #define SOCKET_ERROR -1
62 #define closesocket(A) close(A)
63 #endif
64 
65 #ifdef HAVE_GETPWUID
66 struct passwd *getpwuid(uid_t);
67 char* getlogin(void);
68 #endif
69 
70 #ifdef _WIN32
is_NT(void)71 static my_bool is_NT(void)
72 {
73   char *os=getenv("OS");
74   return (os && !strcmp(os, "Windows_NT")) ? 1 : 0;
75 }
76 #endif
77 
78 
79 int mysql_init_character_set(MYSQL *mysql);
80 
81 MYSQL * STDCALL
mysql_real_connect(MYSQL * mysql,const char * host,const char * user,const char * passwd,const char * db,uint port,const char * unix_socket,ulong client_flag)82 mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
83 		   const char *passwd, const char *db,
84 		   uint port, const char *unix_socket,ulong client_flag)
85 {
86   char name_buff[USERNAME_LENGTH + 1];
87 
88   DBUG_ENTER("mysql_real_connect");
89   DBUG_PRINT("enter",("host: %s  db: %s  user: %s (libmysqld)",
90 		      host ? host : "(Null)",
91 		      db ? db : "(Null)",
92 		      user ? user : "(Null)"));
93 
94   /* Test whether we're already connected */
95   if (mysql->server_version)
96   {
97     set_mysql_error(mysql, CR_ALREADY_CONNECTED, unknown_sqlstate);
98     DBUG_RETURN(0);
99   }
100 
101   if (!host || !host[0])
102     host= mysql->options.host;
103 
104   if (mysql->options.methods_to_use == MYSQL_OPT_USE_REMOTE_CONNECTION ||
105       (mysql->options.methods_to_use == MYSQL_OPT_GUESS_CONNECTION &&
106        host && *host && strcmp(host,LOCAL_HOST)))
107     DBUG_RETURN(cli_mysql_real_connect(mysql, host, user,
108 				       passwd, db, port,
109 				       unix_socket, client_flag));
110 
111   mysql->methods= &embedded_methods;
112 
113   /* use default options */
114   if (mysql->options.my_cnf_file || mysql->options.my_cnf_group)
115   {
116     mysql_read_default_options(&mysql->options,
117 			       (mysql->options.my_cnf_file ?
118 				mysql->options.my_cnf_file : "my"),
119 			       mysql->options.my_cnf_group);
120     my_free(mysql->options.my_cnf_file);
121     my_free(mysql->options.my_cnf_group);
122     mysql->options.my_cnf_file=mysql->options.my_cnf_group=0;
123   }
124 
125   if (!db || !db[0])
126     db=mysql->options.db;
127 
128   if (!user || !user[0])
129     user=mysql->options.user;
130 
131 #ifndef NO_EMBEDDED_ACCESS_CHECKS
132   if (!passwd)
133   {
134     passwd=mysql->options.password;
135     if (!passwd)
136       passwd=getenv("MYSQL_PWD");		/* get it from environment */
137   }
138   mysql->passwd= passwd ? my_strdup(PSI_NOT_INSTRUMENTED,
139                                     passwd,MYF(0)) : NULL;
140 #endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
141   if (!user || !user[0])
142   {
143     read_user_name(name_buff);
144     if (name_buff[0])
145       user= name_buff;
146   }
147 
148   if (!user)
149     user= "";
150    /*
151       We need to alloc some space for mysql->info but don't want to
152       put extra 'my_free's in mysql_close.
153       So we alloc it with the 'user' string to be freed at once
154    */
155   mysql->user= my_strdup(PSI_NOT_INSTRUMENTED,
156                          user, MYF(0));
157 
158   port=0;
159   unix_socket=0;
160 
161   client_flag|=mysql->options.client_flag;
162   /* Send client information for access check */
163   client_flag|=CLIENT_CAPABILITIES;
164   if (client_flag & CLIENT_MULTI_STATEMENTS)
165     client_flag|= CLIENT_MULTI_RESULTS;
166   /*
167     no compression in embedded as we don't send any data,
168     and no pluggable auth, as we cannot do a client-server dialog
169   */
170   client_flag&= ~(CLIENT_COMPRESS | CLIENT_PLUGIN_AUTH);
171   if (db)
172     client_flag|=CLIENT_CONNECT_WITH_DB;
173 
174   if (embedded_ssl_check(mysql))
175     goto error;
176 
177   mysql->info_buffer= my_malloc(PSI_NOT_INSTRUMENTED,
178                                 MYSQL_ERRMSG_SIZE, MYF(0));
179   mysql->thd= create_embedded_thd(client_flag);
180 
181   init_embedded_mysql(mysql, client_flag);
182 
183   if (mysql_init_character_set(mysql))
184     goto error;
185 
186   if (check_embedded_connection(mysql, db))
187     goto error;
188 
189   mysql->server_status= SERVER_STATUS_AUTOCOMMIT;
190 
191   if (mysql->options.init_commands)
192   {
193     DYNAMIC_ARRAY *init_commands= mysql->options.init_commands;
194     char **ptr= (char**)init_commands->buffer;
195     char **end= ptr + init_commands->elements;
196 
197     for (; ptr<end; ptr++)
198     {
199       MYSQL_RES *res;
200       if (mysql_query(mysql,*ptr))
201 	goto error;
202       if (mysql->fields)
203       {
204 	if (!(res= (*mysql->methods->use_result)(mysql)))
205 	  goto error;
206 	mysql_free_result(res);
207       }
208     }
209   }
210 
211   DBUG_PRINT("exit",("Mysql handler: 0x%lx", (long) mysql));
212   DBUG_RETURN(mysql);
213 
214 error:
215   DBUG_PRINT("error",("message: %u (%s)",
216                       mysql->net.last_errno,
217                       mysql->net.last_error));
218   {
219     /* Free alloced memory */
220     my_bool free_me=mysql->free_me;
221     free_old_query(mysql);
222     mysql->free_me=0;
223     mysql_close(mysql);
224     mysql->free_me=free_me;
225   }
226   DBUG_RETURN(0);
227 }
228 
229