Fossil SCM

Remove old SSH transport code and spawn remote fossil http as remote SSH command instead. Also make it possible to configure SSH command prior to cloning. Change remote fossil command to be configurable (really this should probably be simply a matter of fixing PATH on remote end).

amb 2013-07-16 05:47 ssh-transport-changes
Commit c38ff36ddf9c0ada13d604dcd18b81f24d795fd7
+18
--- src/cgi.c
+++ src/cgi.c
@@ -1493,5 +1493,23 @@
14931493
cgi_set_status(304,"Not Modified");
14941494
cgi_reset_content();
14951495
cgi_reply();
14961496
fossil_exit(0);
14971497
}
1498
+
1499
+/*
1500
+** Check to see if the remote client is SSH and return
1501
+** its IP or return default
1502
+*/
1503
+const char *cgi_ssh_remote_addr(const char *zDefault){
1504
+ char *zIndex;
1505
+ const char *zSshConn = fossil_getenv("SSH_CONNECTION");
1506
+
1507
+ if( zSshConn && zSshConn[0] ){
1508
+ char *zSshClient = mprintf("%s",zSshConn);
1509
+ if( zIndex = strchr(zSshClient,' ') ){
1510
+ zSshClient[zIndex-zSshClient] = '\0';
1511
+ return zSshClient;
1512
+ }
1513
+ }
1514
+ return zDefault;
1515
+}
14981516
--- src/cgi.c
+++ src/cgi.c
@@ -1493,5 +1493,23 @@
1493 cgi_set_status(304,"Not Modified");
1494 cgi_reset_content();
1495 cgi_reply();
1496 fossil_exit(0);
1497 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1498
--- src/cgi.c
+++ src/cgi.c
@@ -1493,5 +1493,23 @@
1493 cgi_set_status(304,"Not Modified");
1494 cgi_reset_content();
1495 cgi_reply();
1496 fossil_exit(0);
1497 }
1498
1499 /*
1500 ** Check to see if the remote client is SSH and return
1501 ** its IP or return default
1502 */
1503 const char *cgi_ssh_remote_addr(const char *zDefault){
1504 char *zIndex;
1505 const char *zSshConn = fossil_getenv("SSH_CONNECTION");
1506
1507 if( zSshConn && zSshConn[0] ){
1508 char *zSshClient = mprintf("%s",zSshConn);
1509 if( zIndex = strchr(zSshClient,' ') ){
1510 zSshClient[zIndex-zSshClient] = '\0';
1511 return zSshClient;
1512 }
1513 }
1514 return zDefault;
1515 }
1516
+28
--- src/clone.c
+++ src/clone.c
@@ -93,10 +93,12 @@
9393
**
9494
** Options:
9595
** --admin-user|-A USERNAME Make USERNAME the administrator
9696
** --private Also clone private branches
9797
** --ssl-identity=filename Use the SSL identity if requested by the server
98
+** --ssh-fossil|-f /fossil Use this path as remote fossil command
99
+** --ssh-command|-c 'command' Use this SSH command
98100
**
99101
** See also: init
100102
*/
101103
void clone_cmd(void){
102104
char *zPassword;
@@ -103,10 +105,11 @@
103105
const char *zDefaultUser; /* Optional name of the default user */
104106
int nErr = 0;
105107
int bPrivate = 0; /* Also clone private branches */
106108
107109
if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
110
+ clone_ssh_options();
108111
url_proxy_options();
109112
if( g.argc < 4 ){
110113
usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
111114
}
112115
db_open_config(0);
@@ -174,5 +177,30 @@
174177
fossil_print("project-id: %s\n", db_get("project-code", 0));
175178
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
176179
fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
177180
db_end_transaction(0);
178181
}
182
+
183
+void clone_ssh_options(void){
184
+ const char *zSshFossilCmd; /* Path to remote fossil command for SSH */
185
+ const char *zSshCmd; /* SSH command string */
186
+
187
+ zSshFossilCmd = find_option("ssh-fossil","f",1);
188
+ if( zSshFossilCmd && zSshFossilCmd[0] ){
189
+ g.fSshFossilCmd = mprintf("%s", zSshFossilCmd);
190
+ }
191
+ zSshCmd = find_option("ssh-command","c",1);
192
+ if( zSshCmd && zSshCmd[0] ){
193
+ g.fSshCmd = mprintf("%s", zSshCmd);
194
+ }
195
+}
196
+
197
+void clone_ssh_db_options(void){
198
+ if( g.fSshFossilCmd && g.fSshFossilCmd[0] ){
199
+ db_set("ssh-fossil", g.fSshFossilCmd, 0);
200
+ }else{
201
+ g.fSshFossilCmd = db_get("ssh-fossil","fossil");
202
+ }
203
+ if( g.fSshCmd && g.fSshCmd[0] ){
204
+ db_set("ssh-command", g.fSshCmd, 0);
205
+ }
206
+}
179207
--- src/clone.c
+++ src/clone.c
@@ -93,10 +93,12 @@
93 **
94 ** Options:
95 ** --admin-user|-A USERNAME Make USERNAME the administrator
96 ** --private Also clone private branches
97 ** --ssl-identity=filename Use the SSL identity if requested by the server
 
 
98 **
99 ** See also: init
100 */
101 void clone_cmd(void){
102 char *zPassword;
@@ -103,10 +105,11 @@
103 const char *zDefaultUser; /* Optional name of the default user */
104 int nErr = 0;
105 int bPrivate = 0; /* Also clone private branches */
106
107 if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
 
108 url_proxy_options();
109 if( g.argc < 4 ){
110 usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
111 }
112 db_open_config(0);
@@ -174,5 +177,30 @@
174 fossil_print("project-id: %s\n", db_get("project-code", 0));
175 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
176 fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
177 db_end_transaction(0);
178 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
--- src/clone.c
+++ src/clone.c
@@ -93,10 +93,12 @@
93 **
94 ** Options:
95 ** --admin-user|-A USERNAME Make USERNAME the administrator
96 ** --private Also clone private branches
97 ** --ssl-identity=filename Use the SSL identity if requested by the server
98 ** --ssh-fossil|-f /fossil Use this path as remote fossil command
99 ** --ssh-command|-c 'command' Use this SSH command
100 **
101 ** See also: init
102 */
103 void clone_cmd(void){
104 char *zPassword;
@@ -103,10 +105,11 @@
105 const char *zDefaultUser; /* Optional name of the default user */
106 int nErr = 0;
107 int bPrivate = 0; /* Also clone private branches */
108
109 if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
110 clone_ssh_options();
111 url_proxy_options();
112 if( g.argc < 4 ){
113 usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
114 }
115 db_open_config(0);
@@ -174,5 +177,30 @@
177 fossil_print("project-id: %s\n", db_get("project-code", 0));
178 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
179 fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
180 db_end_transaction(0);
181 }
182
183 void clone_ssh_options(void){
184 const char *zSshFossilCmd; /* Path to remote fossil command for SSH */
185 const char *zSshCmd; /* SSH command string */
186
187 zSshFossilCmd = find_option("ssh-fossil","f",1);
188 if( zSshFossilCmd && zSshFossilCmd[0] ){
189 g.fSshFossilCmd = mprintf("%s", zSshFossilCmd);
190 }
191 zSshCmd = find_option("ssh-command","c",1);
192 if( zSshCmd && zSshCmd[0] ){
193 g.fSshCmd = mprintf("%s", zSshCmd);
194 }
195 }
196
197 void clone_ssh_db_options(void){
198 if( g.fSshFossilCmd && g.fSshFossilCmd[0] ){
199 db_set("ssh-fossil", g.fSshFossilCmd, 0);
200 }else{
201 g.fSshFossilCmd = db_get("ssh-fossil","fossil");
202 }
203 if( g.fSshCmd && g.fSshCmd[0] ){
204 db_set("ssh-command", g.fSshCmd, 0);
205 }
206 }
207
+3
--- src/db.c
+++ src/db.c
@@ -2127,10 +2127,11 @@
21272127
{ "proxy", 0, 32, 0, "off" },
21282128
{ "relative-paths",0, 0, 0, "on" },
21292129
{ "repo-cksum", 0, 0, 0, "on" },
21302130
{ "self-register", 0, 0, 0, "off" },
21312131
{ "ssh-command", 0, 40, 0, "" },
2132
+ { "ssh-fossil", 0, 40, 0, "" },
21322133
{ "ssl-ca-location",0, 40, 0, "" },
21332134
{ "ssl-identity", 0, 40, 0, "" },
21342135
#ifdef FOSSIL_ENABLE_TCL
21352136
{ "tcl", 0, 0, 0, "off" },
21362137
{ "tcl-setup", 0, 40, 0, "" },
@@ -2297,10 +2298,12 @@
22972298
** "Anonymous" in e.g. ticketing system. On the other hand
22982299
** users can not be deleted. Default: off.
22992300
**
23002301
** ssh-command Command used to talk to a remote machine with
23012302
** the "ssh://" protocol.
2303
+**
2304
+** ssh-fossil Remote fossil command to run with the "ssh://" protocol.
23022305
**
23032306
** ssl-ca-location The full pathname to a file containing PEM encoded
23042307
** CA root certificates, or a directory of certificates
23052308
** with filenames formed from the certificate hashes as
23062309
** required by OpenSSL.
23072310
--- src/db.c
+++ src/db.c
@@ -2127,10 +2127,11 @@
2127 { "proxy", 0, 32, 0, "off" },
2128 { "relative-paths",0, 0, 0, "on" },
2129 { "repo-cksum", 0, 0, 0, "on" },
2130 { "self-register", 0, 0, 0, "off" },
2131 { "ssh-command", 0, 40, 0, "" },
 
2132 { "ssl-ca-location",0, 40, 0, "" },
2133 { "ssl-identity", 0, 40, 0, "" },
2134 #ifdef FOSSIL_ENABLE_TCL
2135 { "tcl", 0, 0, 0, "off" },
2136 { "tcl-setup", 0, 40, 0, "" },
@@ -2297,10 +2298,12 @@
2297 ** "Anonymous" in e.g. ticketing system. On the other hand
2298 ** users can not be deleted. Default: off.
2299 **
2300 ** ssh-command Command used to talk to a remote machine with
2301 ** the "ssh://" protocol.
 
 
2302 **
2303 ** ssl-ca-location The full pathname to a file containing PEM encoded
2304 ** CA root certificates, or a directory of certificates
2305 ** with filenames formed from the certificate hashes as
2306 ** required by OpenSSL.
2307
--- src/db.c
+++ src/db.c
@@ -2127,10 +2127,11 @@
2127 { "proxy", 0, 32, 0, "off" },
2128 { "relative-paths",0, 0, 0, "on" },
2129 { "repo-cksum", 0, 0, 0, "on" },
2130 { "self-register", 0, 0, 0, "off" },
2131 { "ssh-command", 0, 40, 0, "" },
2132 { "ssh-fossil", 0, 40, 0, "" },
2133 { "ssl-ca-location",0, 40, 0, "" },
2134 { "ssl-identity", 0, 40, 0, "" },
2135 #ifdef FOSSIL_ENABLE_TCL
2136 { "tcl", 0, 0, 0, "off" },
2137 { "tcl-setup", 0, 40, 0, "" },
@@ -2297,10 +2298,12 @@
2298 ** "Anonymous" in e.g. ticketing system. On the other hand
2299 ** users can not be deleted. Default: off.
2300 **
2301 ** ssh-command Command used to talk to a remote machine with
2302 ** the "ssh://" protocol.
2303 **
2304 ** ssh-fossil Remote fossil command to run with the "ssh://" protocol.
2305 **
2306 ** ssl-ca-location The full pathname to a file containing PEM encoded
2307 ** CA root certificates, or a directory of certificates
2308 ** with filenames formed from the certificate hashes as
2309 ** required by OpenSSL.
2310
-3
--- src/http.c
+++ src/http.c
@@ -42,13 +42,10 @@
4242
4343
blob_zero(pLogin);
4444
if( g.urlUser==0 || fossil_strcmp(g.urlUser, "anonymous")==0 ){
4545
return; /* If no login card for users "nobody" and "anonymous" */
4646
}
47
- if( g.urlIsSsh ){
48
- return; /* If no login card for SSH: */
49
- }
5047
blob_zero(&nonce);
5148
blob_zero(&pw);
5249
sha1sum_blob(pPayload, &nonce);
5350
blob_copy(&pw, &nonce);
5451
zLogin = g.urlUser;
5552
--- src/http.c
+++ src/http.c
@@ -42,13 +42,10 @@
42
43 blob_zero(pLogin);
44 if( g.urlUser==0 || fossil_strcmp(g.urlUser, "anonymous")==0 ){
45 return; /* If no login card for users "nobody" and "anonymous" */
46 }
47 if( g.urlIsSsh ){
48 return; /* If no login card for SSH: */
49 }
50 blob_zero(&nonce);
51 blob_zero(&pw);
52 sha1sum_blob(pPayload, &nonce);
53 blob_copy(&pw, &nonce);
54 zLogin = g.urlUser;
55
--- src/http.c
+++ src/http.c
@@ -42,13 +42,10 @@
42
43 blob_zero(pLogin);
44 if( g.urlUser==0 || fossil_strcmp(g.urlUser, "anonymous")==0 ){
45 return; /* If no login card for users "nobody" and "anonymous" */
46 }
 
 
 
47 blob_zero(&nonce);
48 blob_zero(&pw);
49 sha1sum_blob(pPayload, &nonce);
50 blob_copy(&pw, &nonce);
51 zLogin = g.urlUser;
52
--- src/http_transport.c
+++ src/http_transport.c
@@ -99,183 +99,78 @@
9999
#else
100100
static char zDefaultSshCmd[] = "ssh -e none -T";
101101
#endif
102102
103103
/*
104
-** Generate a random SSH link problem keyword
105
-*/
106
-static int random_probe(char *zProbe, int nProbe){
107
- unsigned r[4];
108
- sqlite3_randomness(sizeof(r), r);
109
- sqlite3_snprintf(nProbe, zProbe, "probe-%08x%08x%08x%08x",
110
- r[0], r[1], r[2], r[3]);
111
- return (int)strlen(zProbe);
112
-}
113
-
114
-/*
115
-** Bring up an SSH link. This involves sending some "echo" commands and
116
-** get back appropriate responses. The point is to move past the MOTD and
117
-** verify that the link is working.
118
-*/
119
-static void transport_ssh_startup(void){
120
- char *zIn; /* An input line received back from remote */
121
- int nWait; /* Number of times waiting for the MOTD */
122
- char zProbe[40]; /* Text of the random probe */
123
- int nProbe; /* Size of probe message */
124
- int nIn; /* Size of input */
125
- static const int nBuf = 10000; /* Size of input buffer */
126
-
127
- zIn = fossil_malloc(nBuf);
128
- nProbe = random_probe(zProbe, sizeof(zProbe));
129
- fprintf(sshOut, "echo %s\n", zProbe);
130
- fflush(sshOut);
131
- if( g.fSshTrace ){
132
- printf("Sent: [echo %s]\n", zProbe);
133
- fflush(stdout);
134
- }
135
- memset(zIn, '*', nProbe);
136
- for(nWait=1; nWait<=10; nWait++){
137
- sshin_read(zIn+nProbe, nBuf-nProbe);
138
- if( g.fSshTrace ){
139
- printf("Got back-----------------------------------------------\n"
140
- "%s\n"
141
- "-------------------------------------------------------\n",
142
- zIn+nProbe);
143
- }
144
- if( strstr(zIn, zProbe) ) break;
145
- sqlite3_sleep(100*nWait);
146
- nIn = (int)strlen(zIn);
147
- memcpy(zIn, zIn+(nIn-nProbe), nProbe);
148
- if( g.fSshTrace ){
149
- printf("Fetching more text. Looking for [%s]...\n", zProbe);
150
- fflush(stdout);
151
- }
152
- }
153
- nProbe = random_probe(zProbe, sizeof(zProbe));
154
- fprintf(sshOut, "echo %s\n", zProbe);
155
- fflush(sshOut);
156
- if( g.fSshTrace ){
157
- printf("Sent: [echo %s]\n", zProbe);
158
- fflush(stdout);
159
- }
160
- sshin_read(zIn, nBuf);
161
- if( zIn[0]==0 ){
162
- sqlite3_sleep(250);
163
- sshin_read(zIn, nBuf);
164
- }
165
- if( g.fSshTrace ){
166
- printf("Got back-----------------------------------------------\n"
167
- "%s\n"
168
- "-------------------------------------------------------\n", zIn);
169
- }
170
- if( memcmp(zIn, zProbe, nProbe)!=0 ){
171
- pclose2(sshIn, sshOut, sshPid);
172
- fossil_fatal("ssh connection failed: [%s]", zIn);
173
- }
174
- fossil_free(zIn);
175
-}
176
-
177
-/*
178
-** Global initialization of the transport layer
179
-*/
180
-void transport_global_startup(void){
181
- if( g.urlIsSsh ){
182
- /* Only SSH requires a global initialization. For SSH we need to create
183
- ** and run an SSH command to talk to the remote machine.
184
- */
185
- const char *zSsh; /* The base SSH command */
186
- Blob zCmd; /* The SSH command */
187
- char *zHost; /* The host name to contact */
188
- int n; /* Size of prefix string */
189
-
190
- zSsh = db_get("ssh-command", zDefaultSshCmd);
191
- blob_init(&zCmd, zSsh, -1);
192
- if( g.urlPort!=g.urlDfltPort ){
193
-#ifdef __MINGW32__
194
- blob_appendf(&zCmd, " -P %d", g.urlPort);
195
-#else
196
- blob_appendf(&zCmd, " -p %d", g.urlPort);
197
-#endif
198
- }
199
- fossil_force_newline();
200
- fossil_print("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
201
- if( g.urlUser && g.urlUser[0] ){
202
- zHost = mprintf("%s@%s", g.urlUser, g.urlName);
203
-#ifdef __MINGW32__
204
- /* Only win32 (and specifically PLINK.EXE) support the -pw option */
205
- if( g.urlPasswd && g.urlPasswd[0] ){
206
- Blob pw;
207
- blob_zero(&pw);
208
- if( g.urlPasswd[0]=='*' ){
209
- char *zPrompt;
210
- zPrompt = mprintf("Password for [%s]: ", zHost);
211
- prompt_for_password(zPrompt, &pw, 0);
212
- free(zPrompt);
213
- }else{
214
- blob_init(&pw, g.urlPasswd, -1);
215
- }
216
- blob_append(&zCmd, " -pw ", -1);
217
- shell_escape(&zCmd, blob_str(&pw));
218
- blob_reset(&pw);
219
- fossil_print(" -pw ********"); /* Do not show the password text */
220
- }
221
-#endif
222
- }else{
223
- zHost = mprintf("%s", g.urlName);
224
- }
225
- n = blob_size(&zCmd);
226
- blob_append(&zCmd, " ", 1);
227
- shell_escape(&zCmd, zHost);
228
- if( g.urlShell ){
229
- blob_appendf(&zCmd, " %s", g.urlShell);
230
- }else{
231
-#if defined(FOSSIL_ENABLE_SSH_FAR_SIDE)
232
- /* The following works. But only if the fossil on the remote side
233
- ** is recent enough to support the test-ssh-far-side command. That
234
- ** command was added on 2013-02-06. We will leave this turned off
235
- ** until most fossil servers have upgraded to that version or a later
236
- ** version. The sync will still work as long as the shell on the far
237
- ** side is bash and not tcsh. And if the default far side shell is
238
- ** tcsh, then the shell=/bin/bash query parameter can be used as a
239
- ** work-around. Enable this code after about a year...
240
- */
241
- blob_appendf(&zCmd, " exec %s test-ssh-far-side", g.urlFossil);
242
-#endif
243
- }
244
- fossil_print("%s\n", blob_str(&zCmd)+n); /* Show tail of SSH command */
245
- free(zHost);
246
- popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
247
- if( sshPid==0 ){
248
- fossil_fatal("cannot start ssh tunnel using [%b]", &zCmd);
249
- }
250
- blob_reset(&zCmd);
251
- transport_ssh_startup();
252
- }
253
-}
254
-
255
-/*
256
-** COMMAND: test-ssh-far-side
257
-**
258
-** Read lines of input text, one by one, and evaluate each line using
259
-** system(). The ssh: sync protocol uses this on the far side of the
260
-** SSH link.
261
-*/
262
-void test_ssh_far_side_cmd(void){
263
- int i = 0;
264
- int got;
265
- char zLine[5000];
266
- while( i<sizeof(zLine) ){
267
- got = read(0, zLine+i, 1);
268
- if( got==0 ) return;
269
- if( zLine[i]=='\n' ){
270
- zLine[i] = 0;
271
- system(zLine);
272
- i = 0;
273
- }else{
274
- i++;
275
- }
276
- }
104
+** SSH initialization of the transport layer
105
+*/
106
+int transport_ssh_open(void){
107
+ /* For SSH we need to create and run SSH fossil http
108
+ ** to talk to the remote machine.
109
+ */
110
+ const char *zSsh; /* The base SSH command */
111
+ Blob zCmd; /* The SSH command */
112
+ char *zHost; /* The host name to contact */
113
+ int n; /* Size of prefix string */
114
+
115
+ zSsh = db_get("ssh-command", zDefaultSshCmd);
116
+ blob_init(&zCmd, zSsh, -1);
117
+ if( g.urlPort!=g.urlDfltPort ){
118
+#ifdef __MINGW32__
119
+ blob_appendf(&zCmd, " -P %d", g.urlPort);
120
+#else
121
+ blob_appendf(&zCmd, " -p %d", g.urlPort);
122
+#endif
123
+ }
124
+ fossil_force_newline();
125
+ fossil_print("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
126
+ if( g.urlUser && g.urlUser[0] ){
127
+ zHost = mprintf("%s@%s", g.urlUser, g.urlName);
128
+#ifdef __MINGW32__
129
+ /* Only win32 (and specifically PLINK.EXE) support the -pw option */
130
+ if( g.urlPasswd && g.urlPasswd[0] ){
131
+ Blob pw;
132
+ blob_zero(&pw);
133
+ if( g.urlPasswd[0]=='*' ){
134
+ char *zPrompt;
135
+ zPrompt = mprintf("Password for [%s]: ", zHost);
136
+ prompt_for_password(zPrompt, &pw, 0);
137
+ free(zPrompt);
138
+ }else{
139
+ blob_init(&pw, g.urlPasswd, -1);
140
+ }
141
+ blob_append(&zCmd, " -pw ", -1);
142
+ shell_escape(&zCmd, blob_str(&pw));
143
+ blob_reset(&pw);
144
+ fossil_print(" -pw ********"); /* Do not show the password text */
145
+ }
146
+#endif
147
+ }else{
148
+ zHost = mprintf("%s", g.urlName);
149
+ }
150
+ n = blob_size(&zCmd);
151
+ blob_append(&zCmd, " ", 1);
152
+ shell_escape(&zCmd, zHost);
153
+ if( g.fSshFossilCmd && g.fSshFossilCmd[0] ){
154
+ blob_append(&zCmd, " ", 1);
155
+ shell_escape(&zCmd, mprintf("%s", g.fSshFossilCmd));
156
+ }else{
157
+ blob_append(&zCmd, " fossil", 7);
158
+ }
159
+ blob_append(&zCmd, " http", 5);
160
+ if( g.urlPath && g.urlPath[0] ){
161
+ blob_append(&zCmd, " ", 1);
162
+ shell_escape(&zCmd, mprintf("%s", g.urlPath));
163
+ }
164
+ fossil_print("%s\n", blob_str(&zCmd)+n); /* Show tail of SSH command */
165
+ free(zHost);
166
+ popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
167
+ if( sshPid==0 ){
168
+ socket_set_errmsg("cannot start ssh tunnel using [%b]", &zCmd);
169
+ }
170
+ blob_reset(&zCmd);
171
+ return sshPid==0;
277172
}
278173
279174
/*
280175
** Open a connection to the server. The server is defined by the following
281176
** global variables:
@@ -288,19 +183,12 @@
288183
*/
289184
int transport_open(void){
290185
int rc = 0;
291186
if( transport.isOpen==0 ){
292187
if( g.urlIsSsh ){
293
- Blob cmd;
294
- blob_zero(&cmd);
295
- shell_escape(&cmd, g.urlFossil);
296
- blob_append(&cmd, " test-http ", -1);
297
- shell_escape(&cmd, g.urlPath);
298
- fprintf(sshOut, "%s || true\n", blob_str(&cmd));
299
- fflush(sshOut);
300
- if( g.fSshTrace ) printf("Sent: [%s]\n", blob_str(&cmd));
301
- blob_reset(&cmd);
188
+ rc = transport_ssh_open();
189
+ if( rc==0 ) transport.isOpen = 1;
302190
}else if( g.urlIsHttps ){
303191
#ifdef FOSSIL_ENABLE_SSL
304192
rc = ssl_open();
305193
if( rc==0 ) transport.isOpen = 1;
306194
#else
@@ -340,11 +228,11 @@
340228
if( transport.pLog ){
341229
fclose(transport.pLog);
342230
transport.pLog = 0;
343231
}
344232
if( g.urlIsSsh ){
345
- /* No-op */
233
+ transport_ssh_close();
346234
}else if( g.urlIsHttps ){
347235
#ifdef FOSSIL_ENABLE_SSL
348236
ssl_close();
349237
#endif
350238
}else if( g.urlIsFile ){
@@ -399,13 +287,11 @@
399287
/*
400288
** This routine is called when the outbound message is complete and
401289
** it is time to being receiving a reply.
402290
*/
403291
void transport_flip(void){
404
- if( g.urlIsSsh ){
405
- fprintf(sshOut, "\n\n");
406
- }else if( g.urlIsFile ){
292
+ if( g.urlIsFile ){
407293
char *zCmd;
408294
fclose(transport.pFile);
409295
zCmd = mprintf("\"%s\" http \"%s\" \"%s\" \"%s\" 127.0.0.1 --localauth",
410296
g.nameOfExe, g.urlName, transport.zOutFile, transport.zInFile
411297
);
@@ -582,19 +468,23 @@
582468
if( g.fSshTrace ) printf("Got line: [%s]\n", &transport.pBuf[iStart]);
583469
return &transport.pBuf[iStart];
584470
}
585471
586472
void transport_global_shutdown(void){
587
- if( g.urlIsSsh && sshPid ){
588
- /*printf("Closing SSH tunnel: ");*/
589
- fflush(stdout);
590
- pclose2(sshIn, sshOut, sshPid);
591
- sshPid = 0;
592
- }
473
+ transport_ssh_close();
593474
if( g.urlIsHttps ){
594475
#ifdef FOSSIL_ENABLE_SSL
595476
ssl_global_shutdown();
596477
#endif
597478
}else{
598479
socket_global_shutdown();
599480
}
600481
}
482
+
483
+void transport_ssh_close(void){
484
+ if( g.urlIsSsh && sshPid ){
485
+ /*printf("Closing SSH tunnel: ");*/
486
+ fflush(stdout);
487
+ pclose2(sshIn, sshOut, sshPid);
488
+ sshPid = 0;
489
+ }
490
+}
601491
--- src/http_transport.c
+++ src/http_transport.c
@@ -99,183 +99,78 @@
99 #else
100 static char zDefaultSshCmd[] = "ssh -e none -T";
101 #endif
102
103 /*
104 ** Generate a random SSH link problem keyword
105 */
106 static int random_probe(char *zProbe, int nProbe){
107 unsigned r[4];
108 sqlite3_randomness(sizeof(r), r);
109 sqlite3_snprintf(nProbe, zProbe, "probe-%08x%08x%08x%08x",
110 r[0], r[1], r[2], r[3]);
111 return (int)strlen(zProbe);
112 }
113
114 /*
115 ** Bring up an SSH link. This involves sending some "echo" commands and
116 ** get back appropriate responses. The point is to move past the MOTD and
117 ** verify that the link is working.
118 */
119 static void transport_ssh_startup(void){
120 char *zIn; /* An input line received back from remote */
121 int nWait; /* Number of times waiting for the MOTD */
122 char zProbe[40]; /* Text of the random probe */
123 int nProbe; /* Size of probe message */
124 int nIn; /* Size of input */
125 static const int nBuf = 10000; /* Size of input buffer */
126
127 zIn = fossil_malloc(nBuf);
128 nProbe = random_probe(zProbe, sizeof(zProbe));
129 fprintf(sshOut, "echo %s\n", zProbe);
130 fflush(sshOut);
131 if( g.fSshTrace ){
132 printf("Sent: [echo %s]\n", zProbe);
133 fflush(stdout);
134 }
135 memset(zIn, '*', nProbe);
136 for(nWait=1; nWait<=10; nWait++){
137 sshin_read(zIn+nProbe, nBuf-nProbe);
138 if( g.fSshTrace ){
139 printf("Got back-----------------------------------------------\n"
140 "%s\n"
141 "-------------------------------------------------------\n",
142 zIn+nProbe);
143 }
144 if( strstr(zIn, zProbe) ) break;
145 sqlite3_sleep(100*nWait);
146 nIn = (int)strlen(zIn);
147 memcpy(zIn, zIn+(nIn-nProbe), nProbe);
148 if( g.fSshTrace ){
149 printf("Fetching more text. Looking for [%s]...\n", zProbe);
150 fflush(stdout);
151 }
152 }
153 nProbe = random_probe(zProbe, sizeof(zProbe));
154 fprintf(sshOut, "echo %s\n", zProbe);
155 fflush(sshOut);
156 if( g.fSshTrace ){
157 printf("Sent: [echo %s]\n", zProbe);
158 fflush(stdout);
159 }
160 sshin_read(zIn, nBuf);
161 if( zIn[0]==0 ){
162 sqlite3_sleep(250);
163 sshin_read(zIn, nBuf);
164 }
165 if( g.fSshTrace ){
166 printf("Got back-----------------------------------------------\n"
167 "%s\n"
168 "-------------------------------------------------------\n", zIn);
169 }
170 if( memcmp(zIn, zProbe, nProbe)!=0 ){
171 pclose2(sshIn, sshOut, sshPid);
172 fossil_fatal("ssh connection failed: [%s]", zIn);
173 }
174 fossil_free(zIn);
175 }
176
177 /*
178 ** Global initialization of the transport layer
179 */
180 void transport_global_startup(void){
181 if( g.urlIsSsh ){
182 /* Only SSH requires a global initialization. For SSH we need to create
183 ** and run an SSH command to talk to the remote machine.
184 */
185 const char *zSsh; /* The base SSH command */
186 Blob zCmd; /* The SSH command */
187 char *zHost; /* The host name to contact */
188 int n; /* Size of prefix string */
189
190 zSsh = db_get("ssh-command", zDefaultSshCmd);
191 blob_init(&zCmd, zSsh, -1);
192 if( g.urlPort!=g.urlDfltPort ){
193 #ifdef __MINGW32__
194 blob_appendf(&zCmd, " -P %d", g.urlPort);
195 #else
196 blob_appendf(&zCmd, " -p %d", g.urlPort);
197 #endif
198 }
199 fossil_force_newline();
200 fossil_print("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
201 if( g.urlUser && g.urlUser[0] ){
202 zHost = mprintf("%s@%s", g.urlUser, g.urlName);
203 #ifdef __MINGW32__
204 /* Only win32 (and specifically PLINK.EXE) support the -pw option */
205 if( g.urlPasswd && g.urlPasswd[0] ){
206 Blob pw;
207 blob_zero(&pw);
208 if( g.urlPasswd[0]=='*' ){
209 char *zPrompt;
210 zPrompt = mprintf("Password for [%s]: ", zHost);
211 prompt_for_password(zPrompt, &pw, 0);
212 free(zPrompt);
213 }else{
214 blob_init(&pw, g.urlPasswd, -1);
215 }
216 blob_append(&zCmd, " -pw ", -1);
217 shell_escape(&zCmd, blob_str(&pw));
218 blob_reset(&pw);
219 fossil_print(" -pw ********"); /* Do not show the password text */
220 }
221 #endif
222 }else{
223 zHost = mprintf("%s", g.urlName);
224 }
225 n = blob_size(&zCmd);
226 blob_append(&zCmd, " ", 1);
227 shell_escape(&zCmd, zHost);
228 if( g.urlShell ){
229 blob_appendf(&zCmd, " %s", g.urlShell);
230 }else{
231 #if defined(FOSSIL_ENABLE_SSH_FAR_SIDE)
232 /* The following works. But only if the fossil on the remote side
233 ** is recent enough to support the test-ssh-far-side command. That
234 ** command was added on 2013-02-06. We will leave this turned off
235 ** until most fossil servers have upgraded to that version or a later
236 ** version. The sync will still work as long as the shell on the far
237 ** side is bash and not tcsh. And if the default far side shell is
238 ** tcsh, then the shell=/bin/bash query parameter can be used as a
239 ** work-around. Enable this code after about a year...
240 */
241 blob_appendf(&zCmd, " exec %s test-ssh-far-side", g.urlFossil);
242 #endif
243 }
244 fossil_print("%s\n", blob_str(&zCmd)+n); /* Show tail of SSH command */
245 free(zHost);
246 popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
247 if( sshPid==0 ){
248 fossil_fatal("cannot start ssh tunnel using [%b]", &zCmd);
249 }
250 blob_reset(&zCmd);
251 transport_ssh_startup();
252 }
253 }
254
255 /*
256 ** COMMAND: test-ssh-far-side
257 **
258 ** Read lines of input text, one by one, and evaluate each line using
259 ** system(). The ssh: sync protocol uses this on the far side of the
260 ** SSH link.
261 */
262 void test_ssh_far_side_cmd(void){
263 int i = 0;
264 int got;
265 char zLine[5000];
266 while( i<sizeof(zLine) ){
267 got = read(0, zLine+i, 1);
268 if( got==0 ) return;
269 if( zLine[i]=='\n' ){
270 zLine[i] = 0;
271 system(zLine);
272 i = 0;
273 }else{
274 i++;
275 }
276 }
277 }
278
279 /*
280 ** Open a connection to the server. The server is defined by the following
281 ** global variables:
@@ -288,19 +183,12 @@
288 */
289 int transport_open(void){
290 int rc = 0;
291 if( transport.isOpen==0 ){
292 if( g.urlIsSsh ){
293 Blob cmd;
294 blob_zero(&cmd);
295 shell_escape(&cmd, g.urlFossil);
296 blob_append(&cmd, " test-http ", -1);
297 shell_escape(&cmd, g.urlPath);
298 fprintf(sshOut, "%s || true\n", blob_str(&cmd));
299 fflush(sshOut);
300 if( g.fSshTrace ) printf("Sent: [%s]\n", blob_str(&cmd));
301 blob_reset(&cmd);
302 }else if( g.urlIsHttps ){
303 #ifdef FOSSIL_ENABLE_SSL
304 rc = ssl_open();
305 if( rc==0 ) transport.isOpen = 1;
306 #else
@@ -340,11 +228,11 @@
340 if( transport.pLog ){
341 fclose(transport.pLog);
342 transport.pLog = 0;
343 }
344 if( g.urlIsSsh ){
345 /* No-op */
346 }else if( g.urlIsHttps ){
347 #ifdef FOSSIL_ENABLE_SSL
348 ssl_close();
349 #endif
350 }else if( g.urlIsFile ){
@@ -399,13 +287,11 @@
399 /*
400 ** This routine is called when the outbound message is complete and
401 ** it is time to being receiving a reply.
402 */
403 void transport_flip(void){
404 if( g.urlIsSsh ){
405 fprintf(sshOut, "\n\n");
406 }else if( g.urlIsFile ){
407 char *zCmd;
408 fclose(transport.pFile);
409 zCmd = mprintf("\"%s\" http \"%s\" \"%s\" \"%s\" 127.0.0.1 --localauth",
410 g.nameOfExe, g.urlName, transport.zOutFile, transport.zInFile
411 );
@@ -582,19 +468,23 @@
582 if( g.fSshTrace ) printf("Got line: [%s]\n", &transport.pBuf[iStart]);
583 return &transport.pBuf[iStart];
584 }
585
586 void transport_global_shutdown(void){
587 if( g.urlIsSsh && sshPid ){
588 /*printf("Closing SSH tunnel: ");*/
589 fflush(stdout);
590 pclose2(sshIn, sshOut, sshPid);
591 sshPid = 0;
592 }
593 if( g.urlIsHttps ){
594 #ifdef FOSSIL_ENABLE_SSL
595 ssl_global_shutdown();
596 #endif
597 }else{
598 socket_global_shutdown();
599 }
600 }
 
 
 
 
 
 
 
 
 
601
--- src/http_transport.c
+++ src/http_transport.c
@@ -99,183 +99,78 @@
99 #else
100 static char zDefaultSshCmd[] = "ssh -e none -T";
101 #endif
102
103 /*
104 ** SSH initialization of the transport layer
105 */
106 int transport_ssh_open(void){
107 /* For SSH we need to create and run SSH fossil http
108 ** to talk to the remote machine.
109 */
110 const char *zSsh; /* The base SSH command */
111 Blob zCmd; /* The SSH command */
112 char *zHost; /* The host name to contact */
113 int n; /* Size of prefix string */
114
115 zSsh = db_get("ssh-command", zDefaultSshCmd);
116 blob_init(&zCmd, zSsh, -1);
117 if( g.urlPort!=g.urlDfltPort ){
118 #ifdef __MINGW32__
119 blob_appendf(&zCmd, " -P %d", g.urlPort);
120 #else
121 blob_appendf(&zCmd, " -p %d", g.urlPort);
122 #endif
123 }
124 fossil_force_newline();
125 fossil_print("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
126 if( g.urlUser && g.urlUser[0] ){
127 zHost = mprintf("%s@%s", g.urlUser, g.urlName);
128 #ifdef __MINGW32__
129 /* Only win32 (and specifically PLINK.EXE) support the -pw option */
130 if( g.urlPasswd && g.urlPasswd[0] ){
131 Blob pw;
132 blob_zero(&pw);
133 if( g.urlPasswd[0]=='*' ){
134 char *zPrompt;
135 zPrompt = mprintf("Password for [%s]: ", zHost);
136 prompt_for_password(zPrompt, &pw, 0);
137 free(zPrompt);
138 }else{
139 blob_init(&pw, g.urlPasswd, -1);
140 }
141 blob_append(&zCmd, " -pw ", -1);
142 shell_escape(&zCmd, blob_str(&pw));
143 blob_reset(&pw);
144 fossil_print(" -pw ********"); /* Do not show the password text */
145 }
146 #endif
147 }else{
148 zHost = mprintf("%s", g.urlName);
149 }
150 n = blob_size(&zCmd);
151 blob_append(&zCmd, " ", 1);
152 shell_escape(&zCmd, zHost);
153 if( g.fSshFossilCmd && g.fSshFossilCmd[0] ){
154 blob_append(&zCmd, " ", 1);
155 shell_escape(&zCmd, mprintf("%s", g.fSshFossilCmd));
156 }else{
157 blob_append(&zCmd, " fossil", 7);
158 }
159 blob_append(&zCmd, " http", 5);
160 if( g.urlPath && g.urlPath[0] ){
161 blob_append(&zCmd, " ", 1);
162 shell_escape(&zCmd, mprintf("%s", g.urlPath));
163 }
164 fossil_print("%s\n", blob_str(&zCmd)+n); /* Show tail of SSH command */
165 free(zHost);
166 popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
167 if( sshPid==0 ){
168 socket_set_errmsg("cannot start ssh tunnel using [%b]", &zCmd);
169 }
170 blob_reset(&zCmd);
171 return sshPid==0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172 }
173
174 /*
175 ** Open a connection to the server. The server is defined by the following
176 ** global variables:
@@ -288,19 +183,12 @@
183 */
184 int transport_open(void){
185 int rc = 0;
186 if( transport.isOpen==0 ){
187 if( g.urlIsSsh ){
188 rc = transport_ssh_open();
189 if( rc==0 ) transport.isOpen = 1;
 
 
 
 
 
 
 
190 }else if( g.urlIsHttps ){
191 #ifdef FOSSIL_ENABLE_SSL
192 rc = ssl_open();
193 if( rc==0 ) transport.isOpen = 1;
194 #else
@@ -340,11 +228,11 @@
228 if( transport.pLog ){
229 fclose(transport.pLog);
230 transport.pLog = 0;
231 }
232 if( g.urlIsSsh ){
233 transport_ssh_close();
234 }else if( g.urlIsHttps ){
235 #ifdef FOSSIL_ENABLE_SSL
236 ssl_close();
237 #endif
238 }else if( g.urlIsFile ){
@@ -399,13 +287,11 @@
287 /*
288 ** This routine is called when the outbound message is complete and
289 ** it is time to being receiving a reply.
290 */
291 void transport_flip(void){
292 if( g.urlIsFile ){
 
 
293 char *zCmd;
294 fclose(transport.pFile);
295 zCmd = mprintf("\"%s\" http \"%s\" \"%s\" \"%s\" 127.0.0.1 --localauth",
296 g.nameOfExe, g.urlName, transport.zOutFile, transport.zInFile
297 );
@@ -582,19 +468,23 @@
468 if( g.fSshTrace ) printf("Got line: [%s]\n", &transport.pBuf[iStart]);
469 return &transport.pBuf[iStart];
470 }
471
472 void transport_global_shutdown(void){
473 transport_ssh_close();
 
 
 
 
 
474 if( g.urlIsHttps ){
475 #ifdef FOSSIL_ENABLE_SSL
476 ssl_global_shutdown();
477 #endif
478 }else{
479 socket_global_shutdown();
480 }
481 }
482
483 void transport_ssh_close(void){
484 if( g.urlIsSsh && sshPid ){
485 /*printf("Closing SSH tunnel: ");*/
486 fflush(stdout);
487 pclose2(sshIn, sshOut, sshPid);
488 sshPid = 0;
489 }
490 }
491
-1
--- src/json.c
+++ src/json.c
@@ -1307,11 +1307,10 @@
13071307
CSTR(g, urlPath);
13081308
CSTR(g, urlUser);
13091309
CSTR(g, urlPasswd);
13101310
CSTR(g, urlCanonical);
13111311
CSTR(g, urlProxyAuth);
1312
- CSTR(g, urlFossil);
13131312
CSTR(g, zLogin);
13141313
CSTR(g, zSSLIdentity);
13151314
CSTR(g, zIpAddr);
13161315
CSTR(g, zNonce);
13171316
CSTR(g, zCsrfToken);
13181317
--- src/json.c
+++ src/json.c
@@ -1307,11 +1307,10 @@
1307 CSTR(g, urlPath);
1308 CSTR(g, urlUser);
1309 CSTR(g, urlPasswd);
1310 CSTR(g, urlCanonical);
1311 CSTR(g, urlProxyAuth);
1312 CSTR(g, urlFossil);
1313 CSTR(g, zLogin);
1314 CSTR(g, zSSLIdentity);
1315 CSTR(g, zIpAddr);
1316 CSTR(g, zNonce);
1317 CSTR(g, zCsrfToken);
1318
--- src/json.c
+++ src/json.c
@@ -1307,11 +1307,10 @@
1307 CSTR(g, urlPath);
1308 CSTR(g, urlUser);
1309 CSTR(g, urlPasswd);
1310 CSTR(g, urlCanonical);
1311 CSTR(g, urlProxyAuth);
 
1312 CSTR(g, zLogin);
1313 CSTR(g, zSSLIdentity);
1314 CSTR(g, zIpAddr);
1315 CSTR(g, zNonce);
1316 CSTR(g, zCsrfToken);
1317
+8 -2
--- src/main.c
+++ src/main.c
@@ -134,10 +134,12 @@
134134
int fSqlPrint; /* True if -sqlprint flag is present */
135135
int fQuiet; /* True if -quiet flag is present */
136136
int fHttpTrace; /* Trace outbound HTTP requests */
137137
int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */
138138
int fSshTrace; /* Trace the SSH setup traffic */
139
+ char *fSshFossilCmd; /* Path to remoe fossil command for SSH */
140
+ char *fSshCmd; /* SSH command string */
139141
int fNoSync; /* Do not do an autosync ever. --nosync */
140142
char *zPath; /* Name of webpage being served */
141143
char *zExtra; /* Extra path information past the webpage name */
142144
char *zBaseURL; /* Full text of the URL being served */
143145
char *zTop; /* Parent directory of zPath */
@@ -173,12 +175,10 @@
173175
char *urlPath; /* Pathname for http: */
174176
char *urlUser; /* User id for http: */
175177
char *urlPasswd; /* Password for http: */
176178
char *urlCanonical; /* Canonical representation of the URL */
177179
char *urlProxyAuth; /* Proxy-Authorizer: string */
178
- char *urlFossil; /* The fossil query parameter on ssh: */
179
- char *urlShell; /* The shell query parameter on ssh: */
180180
unsigned urlFlags; /* Boolean flags controlling URL processing */
181181
182182
const char *zLogin; /* Login name. "" if not logged in. */
183183
const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
184184
** SSL client identity */
@@ -578,10 +578,12 @@
578578
g.fQuiet = find_option("quiet", 0, 0)!=0;
579579
g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
580580
g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
581581
g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
582582
g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
583
+ g.fSshFossilCmd = 0;
584
+ g.fSshCmd = 0;
583585
if( g.fSqlTrace ) g.fSqlStats = 1;
584586
g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
585587
g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
586588
g.zLogin = find_option("user", "U", 1);
587589
g.zSSLIdentity = find_option("ssl-identity", 0, 1);
@@ -623,10 +625,11 @@
623625
"%s: could be any of:%s\n"
624626
"%s: use \"help\" for more information\n",
625627
g.argv[0], zCmdName, g.argv[0], blob_str(&couldbe), g.argv[0]);
626628
fossil_exit(1);
627629
}
630
+ signal(SIGPIPE,SIG_IGN);
628631
atexit( fossil_atexit );
629632
aCommand[idx].xFunc();
630633
fossil_exit(0);
631634
/*NOT_REACHED*/
632635
return 0;
@@ -1677,10 +1680,13 @@
16771680
}else{
16781681
g.httpIn = stdin;
16791682
g.httpOut = stdout;
16801683
zIpAddr = 0;
16811684
}
1685
+ if( zIpAddr==0 ){
1686
+ zIpAddr = cgi_ssh_remote_addr(0);
1687
+ }
16821688
find_server_repository(0);
16831689
g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
16841690
cgi_handle_http_request(zIpAddr);
16851691
process_one_web_page(zNotFound, glob_create(zFileGlob));
16861692
}
16871693
--- src/main.c
+++ src/main.c
@@ -134,10 +134,12 @@
134 int fSqlPrint; /* True if -sqlprint flag is present */
135 int fQuiet; /* True if -quiet flag is present */
136 int fHttpTrace; /* Trace outbound HTTP requests */
137 int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */
138 int fSshTrace; /* Trace the SSH setup traffic */
 
 
139 int fNoSync; /* Do not do an autosync ever. --nosync */
140 char *zPath; /* Name of webpage being served */
141 char *zExtra; /* Extra path information past the webpage name */
142 char *zBaseURL; /* Full text of the URL being served */
143 char *zTop; /* Parent directory of zPath */
@@ -173,12 +175,10 @@
173 char *urlPath; /* Pathname for http: */
174 char *urlUser; /* User id for http: */
175 char *urlPasswd; /* Password for http: */
176 char *urlCanonical; /* Canonical representation of the URL */
177 char *urlProxyAuth; /* Proxy-Authorizer: string */
178 char *urlFossil; /* The fossil query parameter on ssh: */
179 char *urlShell; /* The shell query parameter on ssh: */
180 unsigned urlFlags; /* Boolean flags controlling URL processing */
181
182 const char *zLogin; /* Login name. "" if not logged in. */
183 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
184 ** SSL client identity */
@@ -578,10 +578,12 @@
578 g.fQuiet = find_option("quiet", 0, 0)!=0;
579 g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
580 g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
581 g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
582 g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
 
 
583 if( g.fSqlTrace ) g.fSqlStats = 1;
584 g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
585 g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
586 g.zLogin = find_option("user", "U", 1);
587 g.zSSLIdentity = find_option("ssl-identity", 0, 1);
@@ -623,10 +625,11 @@
623 "%s: could be any of:%s\n"
624 "%s: use \"help\" for more information\n",
625 g.argv[0], zCmdName, g.argv[0], blob_str(&couldbe), g.argv[0]);
626 fossil_exit(1);
627 }
 
628 atexit( fossil_atexit );
629 aCommand[idx].xFunc();
630 fossil_exit(0);
631 /*NOT_REACHED*/
632 return 0;
@@ -1677,10 +1680,13 @@
1677 }else{
1678 g.httpIn = stdin;
1679 g.httpOut = stdout;
1680 zIpAddr = 0;
1681 }
 
 
 
1682 find_server_repository(0);
1683 g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
1684 cgi_handle_http_request(zIpAddr);
1685 process_one_web_page(zNotFound, glob_create(zFileGlob));
1686 }
1687
--- src/main.c
+++ src/main.c
@@ -134,10 +134,12 @@
134 int fSqlPrint; /* True if -sqlprint flag is present */
135 int fQuiet; /* True if -quiet flag is present */
136 int fHttpTrace; /* Trace outbound HTTP requests */
137 int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */
138 int fSshTrace; /* Trace the SSH setup traffic */
139 char *fSshFossilCmd; /* Path to remoe fossil command for SSH */
140 char *fSshCmd; /* SSH command string */
141 int fNoSync; /* Do not do an autosync ever. --nosync */
142 char *zPath; /* Name of webpage being served */
143 char *zExtra; /* Extra path information past the webpage name */
144 char *zBaseURL; /* Full text of the URL being served */
145 char *zTop; /* Parent directory of zPath */
@@ -173,12 +175,10 @@
175 char *urlPath; /* Pathname for http: */
176 char *urlUser; /* User id for http: */
177 char *urlPasswd; /* Password for http: */
178 char *urlCanonical; /* Canonical representation of the URL */
179 char *urlProxyAuth; /* Proxy-Authorizer: string */
 
 
180 unsigned urlFlags; /* Boolean flags controlling URL processing */
181
182 const char *zLogin; /* Login name. "" if not logged in. */
183 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
184 ** SSL client identity */
@@ -578,10 +578,12 @@
578 g.fQuiet = find_option("quiet", 0, 0)!=0;
579 g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
580 g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
581 g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
582 g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
583 g.fSshFossilCmd = 0;
584 g.fSshCmd = 0;
585 if( g.fSqlTrace ) g.fSqlStats = 1;
586 g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
587 g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
588 g.zLogin = find_option("user", "U", 1);
589 g.zSSLIdentity = find_option("ssl-identity", 0, 1);
@@ -623,10 +625,11 @@
625 "%s: could be any of:%s\n"
626 "%s: use \"help\" for more information\n",
627 g.argv[0], zCmdName, g.argv[0], blob_str(&couldbe), g.argv[0]);
628 fossil_exit(1);
629 }
630 signal(SIGPIPE,SIG_IGN);
631 atexit( fossil_atexit );
632 aCommand[idx].xFunc();
633 fossil_exit(0);
634 /*NOT_REACHED*/
635 return 0;
@@ -1677,10 +1680,13 @@
1680 }else{
1681 g.httpIn = stdin;
1682 g.httpOut = stdout;
1683 zIpAddr = 0;
1684 }
1685 if( zIpAddr==0 ){
1686 zIpAddr = cgi_ssh_remote_addr(0);
1687 }
1688 find_server_repository(0);
1689 g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
1690 cgi_handle_http_request(zIpAddr);
1691 process_one_web_page(zNotFound, glob_create(zFileGlob));
1692 }
1693
+6 -39
--- src/url.c
+++ src/url.c
@@ -64,11 +64,11 @@
6464
**
6565
** http://userid:password@host:port/path
6666
**
6767
** SSH url format is:
6868
**
69
-** ssh://userid:password@host:port/path?fossil=path/to/fossil.exe
69
+** ssh://userid:password@host:port/path
7070
**
7171
*/
7272
void url_parse(const char *zUrl, unsigned int urlFlags){
7373
int i, j, c;
7474
char *zFile = 0;
@@ -99,12 +99,10 @@
9999
iStart = 8;
100100
}else if( zUrl[0]=='s' ){
101101
g.urlIsSsh = 1;
102102
g.urlProtocol = "ssh";
103103
g.urlDfltPort = 22;
104
- g.urlFossil = "fossil";
105
- g.urlShell = 0;
106104
iStart = 6;
107105
}else{
108106
g.urlIsHttps = 0;
109107
g.urlProtocol = "http";
110108
g.urlDfltPort = 80;
@@ -151,50 +149,21 @@
151149
for(i=0; g.urlPath[i] && g.urlPath[i]!='?'; i++){}
152150
if( g.urlPath[i] ){
153151
g.urlPath[i] = 0;
154152
i++;
155153
}
156
- zExe = mprintf("");
157
- while( g.urlPath[i]!=0 ){
158
- char *zName, *zValue;
159
- zName = &g.urlPath[i];
160
- zValue = zName;
161
- while( g.urlPath[i] && g.urlPath[i]!='=' ){ i++; }
162
- if( g.urlPath[i]=='=' ){
163
- g.urlPath[i] = 0;
164
- i++;
165
- zValue = &g.urlPath[i];
166
- while( g.urlPath[i] && g.urlPath[i]!='&' ){ i++; }
167
- }
168
- if( g.urlPath[i] ){
169
- g.urlPath[i] = 0;
170
- i++;
171
- }
172
- if( fossil_strcmp(zName,"fossil")==0 ){
173
- g.urlFossil = zValue;
174
- dehttpize(g.urlFossil);
175
- zExe = mprintf("%cfossil=%T", cQuerySep, g.urlFossil);
176
- cQuerySep = '&';
177
- }
178
- if( fossil_strcmp(zName,"shell")==0 ){
179
- g.urlShell = zValue;
180
- dehttpize(g.urlShell);
181
- zExe = mprintf("%cshell=%T", cQuerySep, g.urlFossil);
182
- cQuerySep = '&';
183
- }
184
- }
185154
186155
dehttpize(g.urlPath);
187156
if( g.urlDfltPort==g.urlPort ){
188157
g.urlCanonical = mprintf(
189
- "%s://%s%T%T%s",
190
- g.urlProtocol, zLogin, g.urlName, g.urlPath, zExe
158
+ "%s://%s%T%T",
159
+ g.urlProtocol, zLogin, g.urlName, g.urlPath
191160
);
192161
}else{
193162
g.urlCanonical = mprintf(
194
- "%s://%s%T:%d%T%s",
195
- g.urlProtocol, zLogin, g.urlName, g.urlPort, g.urlPath, zExe
163
+ "%s://%s%T:%d%T",
164
+ g.urlProtocol, zLogin, g.urlName, g.urlPort, g.urlPath
196165
);
197166
}
198167
if( g.urlIsSsh && g.urlPath[1] ) g.urlPath++;
199168
free(zLogin);
200169
}else if( strncmp(zUrl, "file:", 5)==0 ){
@@ -276,11 +245,10 @@
276245
fossil_print("g.urlHostname = %s\n", g.urlHostname);
277246
fossil_print("g.urlPath = %s\n", g.urlPath);
278247
fossil_print("g.urlUser = %s\n", g.urlUser);
279248
fossil_print("g.urlPasswd = %s\n", g.urlPasswd);
280249
fossil_print("g.urlCanonical = %s\n", g.urlCanonical);
281
- fossil_print("g.urlFossil = %s\n", g.urlFossil);
282250
fossil_print("g.urlFlags = 0x%02x\n", g.urlFlags);
283251
if( g.urlIsFile || g.urlIsSsh ) break;
284252
if( i==0 ){
285253
fossil_print("********\n");
286254
url_enable_proxy("Using proxy: ");
@@ -439,11 +407,11 @@
439407
/*
440408
** Prompt the user for the password for g.urlUser. Store the result
441409
** in g.urlPasswd.
442410
*/
443411
void url_prompt_for_password(void){
444
- if( g.urlIsSsh || g.urlIsFile ) return;
412
+ if( g.urlIsFile ) return;
445413
if( isatty(fileno(stdin))
446414
&& (g.urlFlags & URL_PROMPT_PW)!=0
447415
&& (g.urlFlags & URL_PROMPTED)==0
448416
){
449417
char *zPrompt = mprintf("\rpassword for %s: ", g.urlUser);
@@ -490,10 +458,9 @@
490458
*/
491459
void url_get_password_if_needed(void){
492460
if( (g.urlUser && g.urlUser[0])
493461
&& (g.urlPasswd==0 || g.urlPasswd[0]==0)
494462
&& isatty(fileno(stdin))
495
- && g.urlIsSsh==0
496463
){
497464
url_prompt_for_password();
498465
}
499466
}
500467
--- src/url.c
+++ src/url.c
@@ -64,11 +64,11 @@
64 **
65 ** http://userid:password@host:port/path
66 **
67 ** SSH url format is:
68 **
69 ** ssh://userid:password@host:port/path?fossil=path/to/fossil.exe
70 **
71 */
72 void url_parse(const char *zUrl, unsigned int urlFlags){
73 int i, j, c;
74 char *zFile = 0;
@@ -99,12 +99,10 @@
99 iStart = 8;
100 }else if( zUrl[0]=='s' ){
101 g.urlIsSsh = 1;
102 g.urlProtocol = "ssh";
103 g.urlDfltPort = 22;
104 g.urlFossil = "fossil";
105 g.urlShell = 0;
106 iStart = 6;
107 }else{
108 g.urlIsHttps = 0;
109 g.urlProtocol = "http";
110 g.urlDfltPort = 80;
@@ -151,50 +149,21 @@
151 for(i=0; g.urlPath[i] && g.urlPath[i]!='?'; i++){}
152 if( g.urlPath[i] ){
153 g.urlPath[i] = 0;
154 i++;
155 }
156 zExe = mprintf("");
157 while( g.urlPath[i]!=0 ){
158 char *zName, *zValue;
159 zName = &g.urlPath[i];
160 zValue = zName;
161 while( g.urlPath[i] && g.urlPath[i]!='=' ){ i++; }
162 if( g.urlPath[i]=='=' ){
163 g.urlPath[i] = 0;
164 i++;
165 zValue = &g.urlPath[i];
166 while( g.urlPath[i] && g.urlPath[i]!='&' ){ i++; }
167 }
168 if( g.urlPath[i] ){
169 g.urlPath[i] = 0;
170 i++;
171 }
172 if( fossil_strcmp(zName,"fossil")==0 ){
173 g.urlFossil = zValue;
174 dehttpize(g.urlFossil);
175 zExe = mprintf("%cfossil=%T", cQuerySep, g.urlFossil);
176 cQuerySep = '&';
177 }
178 if( fossil_strcmp(zName,"shell")==0 ){
179 g.urlShell = zValue;
180 dehttpize(g.urlShell);
181 zExe = mprintf("%cshell=%T", cQuerySep, g.urlFossil);
182 cQuerySep = '&';
183 }
184 }
185
186 dehttpize(g.urlPath);
187 if( g.urlDfltPort==g.urlPort ){
188 g.urlCanonical = mprintf(
189 "%s://%s%T%T%s",
190 g.urlProtocol, zLogin, g.urlName, g.urlPath, zExe
191 );
192 }else{
193 g.urlCanonical = mprintf(
194 "%s://%s%T:%d%T%s",
195 g.urlProtocol, zLogin, g.urlName, g.urlPort, g.urlPath, zExe
196 );
197 }
198 if( g.urlIsSsh && g.urlPath[1] ) g.urlPath++;
199 free(zLogin);
200 }else if( strncmp(zUrl, "file:", 5)==0 ){
@@ -276,11 +245,10 @@
276 fossil_print("g.urlHostname = %s\n", g.urlHostname);
277 fossil_print("g.urlPath = %s\n", g.urlPath);
278 fossil_print("g.urlUser = %s\n", g.urlUser);
279 fossil_print("g.urlPasswd = %s\n", g.urlPasswd);
280 fossil_print("g.urlCanonical = %s\n", g.urlCanonical);
281 fossil_print("g.urlFossil = %s\n", g.urlFossil);
282 fossil_print("g.urlFlags = 0x%02x\n", g.urlFlags);
283 if( g.urlIsFile || g.urlIsSsh ) break;
284 if( i==0 ){
285 fossil_print("********\n");
286 url_enable_proxy("Using proxy: ");
@@ -439,11 +407,11 @@
439 /*
440 ** Prompt the user for the password for g.urlUser. Store the result
441 ** in g.urlPasswd.
442 */
443 void url_prompt_for_password(void){
444 if( g.urlIsSsh || g.urlIsFile ) return;
445 if( isatty(fileno(stdin))
446 && (g.urlFlags & URL_PROMPT_PW)!=0
447 && (g.urlFlags & URL_PROMPTED)==0
448 ){
449 char *zPrompt = mprintf("\rpassword for %s: ", g.urlUser);
@@ -490,10 +458,9 @@
490 */
491 void url_get_password_if_needed(void){
492 if( (g.urlUser && g.urlUser[0])
493 && (g.urlPasswd==0 || g.urlPasswd[0]==0)
494 && isatty(fileno(stdin))
495 && g.urlIsSsh==0
496 ){
497 url_prompt_for_password();
498 }
499 }
500
--- src/url.c
+++ src/url.c
@@ -64,11 +64,11 @@
64 **
65 ** http://userid:password@host:port/path
66 **
67 ** SSH url format is:
68 **
69 ** ssh://userid:password@host:port/path
70 **
71 */
72 void url_parse(const char *zUrl, unsigned int urlFlags){
73 int i, j, c;
74 char *zFile = 0;
@@ -99,12 +99,10 @@
99 iStart = 8;
100 }else if( zUrl[0]=='s' ){
101 g.urlIsSsh = 1;
102 g.urlProtocol = "ssh";
103 g.urlDfltPort = 22;
 
 
104 iStart = 6;
105 }else{
106 g.urlIsHttps = 0;
107 g.urlProtocol = "http";
108 g.urlDfltPort = 80;
@@ -151,50 +149,21 @@
149 for(i=0; g.urlPath[i] && g.urlPath[i]!='?'; i++){}
150 if( g.urlPath[i] ){
151 g.urlPath[i] = 0;
152 i++;
153 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
155 dehttpize(g.urlPath);
156 if( g.urlDfltPort==g.urlPort ){
157 g.urlCanonical = mprintf(
158 "%s://%s%T%T",
159 g.urlProtocol, zLogin, g.urlName, g.urlPath
160 );
161 }else{
162 g.urlCanonical = mprintf(
163 "%s://%s%T:%d%T",
164 g.urlProtocol, zLogin, g.urlName, g.urlPort, g.urlPath
165 );
166 }
167 if( g.urlIsSsh && g.urlPath[1] ) g.urlPath++;
168 free(zLogin);
169 }else if( strncmp(zUrl, "file:", 5)==0 ){
@@ -276,11 +245,10 @@
245 fossil_print("g.urlHostname = %s\n", g.urlHostname);
246 fossil_print("g.urlPath = %s\n", g.urlPath);
247 fossil_print("g.urlUser = %s\n", g.urlUser);
248 fossil_print("g.urlPasswd = %s\n", g.urlPasswd);
249 fossil_print("g.urlCanonical = %s\n", g.urlCanonical);
 
250 fossil_print("g.urlFlags = 0x%02x\n", g.urlFlags);
251 if( g.urlIsFile || g.urlIsSsh ) break;
252 if( i==0 ){
253 fossil_print("********\n");
254 url_enable_proxy("Using proxy: ");
@@ -439,11 +407,11 @@
407 /*
408 ** Prompt the user for the password for g.urlUser. Store the result
409 ** in g.urlPasswd.
410 */
411 void url_prompt_for_password(void){
412 if( g.urlIsFile ) return;
413 if( isatty(fileno(stdin))
414 && (g.urlFlags & URL_PROMPT_PW)!=0
415 && (g.urlFlags & URL_PROMPTED)==0
416 ){
417 char *zPrompt = mprintf("\rpassword for %s: ", g.urlUser);
@@ -490,10 +458,9 @@
458 */
459 void url_get_password_if_needed(void){
460 if( (g.urlUser && g.urlUser[0])
461 && (g.urlPasswd==0 || g.urlPasswd[0]==0)
462 && isatty(fileno(stdin))
 
463 ){
464 url_prompt_for_password();
465 }
466 }
467
+1 -1
--- src/xfer.c
+++ src/xfer.c
@@ -1336,10 +1336,11 @@
13361336
13371337
if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
13381338
if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE))==0
13391339
&& configRcvMask==0 && configSendMask==0 ) return 0;
13401340
1341
+ clone_ssh_db_options();
13411342
transport_stats(0, 0, 1);
13421343
socket_global_init();
13431344
memset(&xfer, 0, sizeof(xfer));
13441345
xfer.pIn = &recv;
13451346
xfer.pOut = &send;
@@ -1387,11 +1388,10 @@
13871388
blob_appendf(&send, "push %s %s\n", zSCode, zPCode);
13881389
nCardSent++;
13891390
if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push";
13901391
}
13911392
manifest_crosslink_begin();
1392
- transport_global_startup();
13931393
if( syncFlags & SYNC_VERBOSE ){
13941394
fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas");
13951395
}
13961396
13971397
while( go ){
13981398
--- src/xfer.c
+++ src/xfer.c
@@ -1336,10 +1336,11 @@
1336
1337 if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
1338 if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE))==0
1339 && configRcvMask==0 && configSendMask==0 ) return 0;
1340
 
1341 transport_stats(0, 0, 1);
1342 socket_global_init();
1343 memset(&xfer, 0, sizeof(xfer));
1344 xfer.pIn = &recv;
1345 xfer.pOut = &send;
@@ -1387,11 +1388,10 @@
1387 blob_appendf(&send, "push %s %s\n", zSCode, zPCode);
1388 nCardSent++;
1389 if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push";
1390 }
1391 manifest_crosslink_begin();
1392 transport_global_startup();
1393 if( syncFlags & SYNC_VERBOSE ){
1394 fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas");
1395 }
1396
1397 while( go ){
1398
--- src/xfer.c
+++ src/xfer.c
@@ -1336,10 +1336,11 @@
1336
1337 if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
1338 if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE))==0
1339 && configRcvMask==0 && configSendMask==0 ) return 0;
1340
1341 clone_ssh_db_options();
1342 transport_stats(0, 0, 1);
1343 socket_global_init();
1344 memset(&xfer, 0, sizeof(xfer));
1345 xfer.pIn = &recv;
1346 xfer.pOut = &send;
@@ -1387,11 +1388,10 @@
1388 blob_appendf(&send, "push %s %s\n", zSCode, zPCode);
1389 nCardSent++;
1390 if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push";
1391 }
1392 manifest_crosslink_begin();
 
1393 if( syncFlags & SYNC_VERBOSE ){
1394 fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas");
1395 }
1396
1397 while( go ){
1398

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button