Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Avoid another attack vector when using SSH sync protocol by not calling a shell interpreter. Fixes only Unix-like environments by using execvp() instead of a string that can be mishandled by /bin/sh. Superseded by [3b191c984b] &co. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | ssh-shell-cleanup |
Files: | files | file ages | folders |
SHA3-256: |
ce7baa9798de21aabfea96f80e0f6159 |
User & Date: | andybradford 2017-08-12 16:20:18 |
Original Comment: | Avoid another attack vector when using SSH sync protocol by not calling a shell interpreter. Fixes only Unix-like environments by using execvp() instead of a string that can be mishandled by /bin/sh. |
Context
2017-08-12
| ||
16:20 | Avoid another attack vector when using SSH sync protocol by not calling a shell interpreter. Fixes only Unix-like environments by using execvp() instead of a string that can be mishandled by /bin/sh. Superseded by [3b191c984b] &co. ... (Closed-Leaf check-in: ce7baa97 user: andybradford tags: ssh-shell-cleanup) | |
04:19 | Typo correction ... (check-in: 45a3d4b1 user: andygoth tags: trunk) | |
Changes
Changes to src/http_transport.c.
︙ | ︙ | |||
101 102 103 104 105 106 107 | /* ** SSH initialization of the transport layer */ int transport_ssh_open(UrlData *pUrlData){ /* For SSH we need to create and run SSH fossil http ** to talk to the remote machine. */ | | | > | | > | | < < | < < < | < | | < > | > | | > > | > > > | | | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | /* ** SSH initialization of the transport layer */ int transport_ssh_open(UrlData *pUrlData){ /* For SSH we need to create and run SSH fossil http ** to talk to the remote machine. */ Blob sshBase; /* The base SSH command */ Blob aArgv[50]; /* The SSH arguments array */ char *zHost; /* The host name to contact */ int n; /* Size of prefix string */ int nToken, i; socket_ssh_resolve_addr(pUrlData); blob_init(&sshBase, db_get("ssh-command", zDefaultSshCmd), -1); blobarray_zero(aArgv, count(aArgv)); n = nToken = blob_tokenize(&sshBase, aArgv, count(aArgv)); if( pUrlData->port!=pUrlData->dfltPort && pUrlData->port ){ #ifdef _WIN32 blob_append(&aArgv[nToken++], "-P", 2); #else blob_append(&aArgv[nToken++], "-p", 2); #endif blob_appendf(&aArgv[nToken++], "%d", pUrlData->port); } if( pUrlData->user && pUrlData->user[0] ){ zHost = mprintf("%s@%s", pUrlData->user, pUrlData->name); }else{ zHost = mprintf("%s", pUrlData->name); } shell_escape(&aArgv[nToken++], stripLeadingMinus(zHost)); shell_escape(&aArgv[nToken++], mprintf("%s", pUrlData->fossil)); blob_append(&aArgv[nToken++], "test-http", 9); if( pUrlData->path && pUrlData->path[0] ){ shell_escape(&aArgv[nToken++], mprintf("%s", stripLeadingMinus(pUrlData->path))); } if( g.fSshTrace ){ for(i=0; i<nToken; i++){ fossil_print("%s ", blob_str(&aArgv[i])); } fossil_force_newline(); } free(zHost); popen2(&aArgv[0], nToken, &sshIn, &sshOut, &sshPid); if( sshPid==0 ){ for(i=n; i<nToken; i++){ blob_appendf(&sshBase, " %b", &aArgv[i]); } socket_set_errmsg("cannot start ssh tunnel using [%b]", &sshBase); } blobarray_reset(aArgv, nToken); return sshPid==0; } /* ** Open a connection to the server. The server is defined by the following ** variables: ** |
︙ | ︙ |
Changes to src/popen.c.
︙ | ︙ | |||
109 110 111 112 113 114 115 | win32_fatal_error("cannot create child process"); } return rc!=0; } #endif /* | | | > | > > > > > | | 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | win32_fatal_error("cannot create child process"); } return rc!=0; } #endif /* ** Create a child process from array of arguments in "aArgv". *ppOut is ** a FILE that becomes the standard input of the child process. ** (The caller writes to *ppOut in order to send text to the child.) ** *ppIn is stdout from the child process. (The caller ** reads from *ppIn in order to receive input from the child.) ** Note that *ppIn is an unbuffered file descriptor, not a FILE. ** The process ID of the child is written into *pChildPid. ** ** Return the number of errors. */ int popen2(Blob *aArgv, int nToken, int *pfdIn, FILE **ppOut, int *pChildPid){ #ifdef _WIN32 HANDLE hStdinRd, hStdinWr, hStdoutRd, hStdoutWr, hStderr; SECURITY_ATTRIBUTES saAttr; DWORD childPid = 0; Blob shellcmd; int fd, i; saAttr.nLength = sizeof(saAttr); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; hStderr = GetStdHandle(STD_ERROR_HANDLE); if( !CreatePipe(&hStdoutRd, &hStdoutWr, &saAttr, 4096) ){ win32_fatal_error("cannot create pipe for stdout"); } SetHandleInformation( hStdoutRd, HANDLE_FLAG_INHERIT, FALSE); if( !CreatePipe(&hStdinRd, &hStdinWr, &saAttr, 4096) ){ win32_fatal_error("cannot create pipe for stdin"); } SetHandleInformation( hStdinWr, HANDLE_FLAG_INHERIT, FALSE); blob_zero(&shellcmd); for(i=0; i<nToken-1; i++){ blob_appendf(&shellcmd, "%b ", aArgv[i]); } blob_trim(&shellcmd); win32_create_child_process(fossil_utf8_to_unicode(blob_str(&shellcmd)), hStdinRd, hStdoutWr, hStderr,&childPid); *pChildPid = childPid; *pfdIn = _open_osfhandle(PTR_TO_INT(hStdoutRd), 0); fd = _open_osfhandle(PTR_TO_INT(hStdinWr), 0); *ppOut = _fdopen(fd, "w"); CloseHandle(hStdinRd); CloseHandle(hStdoutWr); |
︙ | ︙ | |||
174 175 176 177 178 179 180 | close(pout[0]); close(pout[1]); *pChildPid = 0; return 1; } signal(SIGPIPE,SIG_IGN); if( *pChildPid==0 ){ | > | > > > > > | | 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | close(pout[0]); close(pout[1]); *pChildPid = 0; return 1; } signal(SIGPIPE,SIG_IGN); if( *pChildPid==0 ){ char **pzArgs = 0; int fd, i; int nErr = 0; /* This is the child process */ close(0); fd = dup(pout[0]); if( fd!=0 ) nErr++; close(pout[0]); close(pout[1]); close(1); fd = dup(pin[1]); if( fd!=1 ) nErr++; close(pin[0]); close(pin[1]); pzArgs = fossil_malloc( (nToken+1)*sizeof(pzArgs[0]) ); for(i=0; i<nToken; i++){ pzArgs[i] = blob_str(&aArgv[i]); } pzArgs[i] = 0; execvp(pzArgs[0], pzArgs); return 1; }else{ /* This is the parent process */ close(pin[1]); *pfdIn = pin[0]; close(pout[0]); *ppOut = fdopen(pout[1], "w"); |
︙ | ︙ |