Fossil

Check-in [2600f59f2d]
Login

Check-in [2600f59f2d]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Handle --once preference and prevent sending HTTP Authorization when the URL is named on the command line.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | http-auth
Files: files | file ages | folders
SHA1: 2600f59f2d1e983439e55a38717c2de12245a710
User & Date: andybradford 2014-02-01 23:39:36.178
Context
2014-02-02
01:49
Remove the HTTP Authorization setting if the URL is changed with remote-url. ... (check-in: 456a1edd70 user: andybradford tags: http-auth)
2014-02-01
23:39
Handle --once preference and prevent sending HTTP Authorization when the URL is named on the command line. ... (check-in: 2600f59f2d user: andybradford tags: http-auth)
22:06
Only automatically provide Authorization if the URL is HTTPS. User can express preference to use Authorization over unencrypted HTTP via the --httpauth command line option. ... (check-in: 906cfae444 user: andybradford tags: http-auth)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/clone.c.
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
**    --httpauth|-B              Add HTTP Basic Authorization to requests
**
** See also: init
*/
void clone_cmd(void){
  char *zPassword;
  const char *zDefaultUser;   /* Optional name of the default user */
  int fUseHttpAuth;           /* Use HTTP auth if requested by user */
  int nErr = 0;
  int bPrivate = 0;           /* Also clone private branches */
  int urlFlags = URL_PROMPT_PW | URL_REMEMBER;

  if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
  if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER;
  fUseHttpAuth = find_option("httpauth","B",0)!=0;
  zDefaultUser = find_option("admin-user","A",1);
  clone_ssh_find_options();
  url_proxy_options();
  if( g.argc < 4 ){
    usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
  }
  db_open_config(0);







<






|







114
115
116
117
118
119
120

121
122
123
124
125
126
127
128
129
130
131
132
133
134
**    --httpauth|-B              Add HTTP Basic Authorization to requests
**
** See also: init
*/
void clone_cmd(void){
  char *zPassword;
  const char *zDefaultUser;   /* Optional name of the default user */

  int nErr = 0;
  int bPrivate = 0;           /* Also clone private branches */
  int urlFlags = URL_PROMPT_PW | URL_REMEMBER;

  if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
  if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER;
  g.fUseHttpAuth = find_option("httpauth","B",0)!=0;
  zDefaultUser = find_option("admin-user","A",1);
  clone_ssh_find_options();
  url_proxy_options();
  if( g.argc < 4 ){
    usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
  }
  db_open_config(0);
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
    db_begin_transaction();
    db_record_repository_filename(g.argv[3]);
    db_initial_setup(0, 0, zDefaultUser, 0);
    user_select();
    db_set("content-schema", CONTENT_SCHEMA, 0);
    db_set("aux-schema", AUX_SCHEMA, 0);
    db_set("rebuilt", get_version(), 0);
    remember_http_auth(fUseHttpAuth,g.argv[2]);
    url_remember();
    if( g.zSSLIdentity!=0 ){
      /* If the --ssl-identity option was specified, store it as a setting */
      Blob fn;
      blob_zero(&fn);
      file_canonical_name(g.zSSLIdentity, &fn, 0);
      db_set("ssl-identity", blob_str(&fn), 0);







|







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
    db_begin_transaction();
    db_record_repository_filename(g.argv[3]);
    db_initial_setup(0, 0, zDefaultUser, 0);
    user_select();
    db_set("content-schema", CONTENT_SCHEMA, 0);
    db_set("aux-schema", AUX_SCHEMA, 0);
    db_set("rebuilt", get_version(), 0);
    remember_or_get_http_auth(urlFlags & URL_REMEMBER, g.argv[2]);
    url_remember();
    if( g.zSSLIdentity!=0 ){
      /* If the --ssl-identity option was specified, store it as a setting */
      Blob fn;
      blob_zero(&fn);
      file_canonical_name(g.zSSLIdentity, &fn, 0);
      db_set("ssl-identity", blob_str(&fn), 0);
202
203
204
205
206
207
208

209
210

211
212
213
214





215
216
217
218
219
220
221
  db_end_transaction(0);
}

/*
** If user chooses to use HTTP Authentication over unencrypted HTTP,
** remember decision.  Otherwise, if the URL is being changed and no preference
** has been indicated, err on the safe side and revert the decision.

*/
void remember_http_auth(int fUseHttpAuth, const char *zUrl){

  if( fUseHttpAuth==1 ){
    db_set_int("use-http-auth", 1, 0);
  }else if( zUrl && zUrl[0] ){
    db_unset("use-http-auth", 0);





  }
}

/*
** Look for SSH clone command line options and setup in globals.
*/
void clone_ssh_find_options(void){







>

|
>
|
|
|
|
>
>
>
>
>







201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  db_end_transaction(0);
}

/*
** If user chooses to use HTTP Authentication over unencrypted HTTP,
** remember decision.  Otherwise, if the URL is being changed and no preference
** has been indicated, err on the safe side and revert the decision.
** Set the global preference if the URL is not being changed.
*/
void remember_or_get_http_auth(int fRemember, const char *zUrl){
  if( fRemember ){
    if( g.fUseHttpAuth==1 ){
      db_set_int("use-http-auth", 1, 0);
    }else if( zUrl && zUrl[0] ){
      db_unset("use-http-auth", 0);
    }else{
      g.fUseHttpAuth = db_get_boolean("use-http-auth",0)!=0;
    }
  }else if( g.fUseHttpAuth==0 && zUrl==0 ){
    g.fUseHttpAuth = db_get_boolean("use-http-auth",0)!=0;
  }
}

/*
** Look for SSH clone command line options and setup in globals.
*/
void clone_ssh_find_options(void){
Changes to src/http.c.
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  sha1sum_blob(&pw, &sig);
  blob_appendf(pLogin, "login %F %b %b\n", zLogin, &nonce, &sig);
  blob_reset(&pw);
  blob_reset(&sig);
  blob_reset(&nonce);
}

/*
** Use HTTP Basic Authorization if a 401 is seen.
*/
static int fUseHttpAuth = 0;

/*
** Construct an appropriate HTTP request header.  Write the header
** into pHdr.  This routine initializes the pHdr blob.  pPayload is
** the complete payload (including the login card) already compressed.
*/
static void http_build_header(Blob *pPayload, Blob *pHdr){
  int i;
  const char *zSep;

  blob_zero(pHdr);
  i = strlen(g.urlPath);
  if( i>0 && g.urlPath[i-1]=='/' ){
    zSep = "";
  }else{
    zSep = "/";
  }
  blob_appendf(pHdr, "POST %s%sxfer/xfer HTTP/1.0\r\n", g.urlPath, zSep);
  if( g.urlProxyAuth ){
    blob_appendf(pHdr, "Proxy-Authorization: %s\r\n", g.urlProxyAuth);
  }
  if( g.urlPasswd && g.urlUser && fUseHttpAuth ){
    char *zCredentials = mprintf("%s:%s", g.urlUser, g.urlPasswd);
    char *zEncoded = encode64(zCredentials, -1);
    blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded);
    fossil_free(zEncoded);
    fossil_free(zCredentials);
  }
  blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);







<
<
<
<
<




















|







74
75
76
77
78
79
80





81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
  sha1sum_blob(&pw, &sig);
  blob_appendf(pLogin, "login %F %b %b\n", zLogin, &nonce, &sig);
  blob_reset(&pw);
  blob_reset(&sig);
  blob_reset(&nonce);
}






/*
** Construct an appropriate HTTP request header.  Write the header
** into pHdr.  This routine initializes the pHdr blob.  pPayload is
** the complete payload (including the login card) already compressed.
*/
static void http_build_header(Blob *pPayload, Blob *pHdr){
  int i;
  const char *zSep;

  blob_zero(pHdr);
  i = strlen(g.urlPath);
  if( i>0 && g.urlPath[i-1]=='/' ){
    zSep = "";
  }else{
    zSep = "/";
  }
  blob_appendf(pHdr, "POST %s%sxfer/xfer HTTP/1.0\r\n", g.urlPath, zSep);
  if( g.urlProxyAuth ){
    blob_appendf(pHdr, "Proxy-Authorization: %s\r\n", g.urlProxyAuth);
  }
  if( g.urlPasswd && g.urlUser && g.fUseHttpAuth ){
    char *zCredentials = mprintf("%s:%s", g.urlUser, g.urlPasswd);
    char *zEncoded = encode64(zCredentials, -1);
    blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded);
    fossil_free(zEncoded);
    fossil_free(zCredentials);
  }
  blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
203
204
205
206
207
208
209
210

211
212
213
214
215
216
217
218
  closeConnection = 1;
  iLength = -1;
  while( (zLine = transport_receive_line(GLOBAL_URL()))!=0 && zLine[0]!=0 ){
    /* printf("[%s]\n", zLine); fflush(stdout); */
    if( fossil_strnicmp(zLine, "http/1.", 7)==0 ){
      if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err;
      if( rc==401 ){
        if( g.urlIsHttps || db_get_boolean("use-http-auth",0)!=0 ){

          fUseHttpAuth = 1;
          transport_close(GLOBAL_URL());
          if( --maxRedirect == 0 ){
            fossil_fatal("http authorization limit exceeded");
          }
          return http_exchange(pSend, pReply, useLogin, maxRedirect);
        }else{
          fossil_warning(







|
>
|







198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  closeConnection = 1;
  iLength = -1;
  while( (zLine = transport_receive_line(GLOBAL_URL()))!=0 && zLine[0]!=0 ){
    /* printf("[%s]\n", zLine); fflush(stdout); */
    if( fossil_strnicmp(zLine, "http/1.", 7)==0 ){
      if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err;
      if( rc==401 ){
        if( g.urlIsHttps || g.fUseHttpAuth ){
          /* set g.fUseHttpAuth to avoid loop when doing HTTPS */
          g.fUseHttpAuth = 1;
          transport_close(GLOBAL_URL());
          if( --maxRedirect == 0 ){
            fossil_fatal("http authorization limit exceeded");
          }
          return http_exchange(pSend, pReply, useLogin, maxRedirect);
        }else{
          fossil_warning(
Changes to src/main.c.
137
138
139
140
141
142
143

144
145
146
147
148
149
150
  char *zLocalRoot;       /* The directory holding the  local database */
  int minPrefix;          /* Number of digits needed for a distinct UUID */
  int fSqlTrace;          /* True if --sqltrace flag is present */
  int fSqlStats;          /* True if --sqltrace or --sqlstats are present */
  int fSqlPrint;          /* True if -sqlprint flag is present */
  int fQuiet;             /* True if -quiet flag is present */
  int fHttpTrace;         /* Trace outbound HTTP requests */

  int fSystemTrace;       /* Trace calls to fossil_system(), --systemtrace */
  int fSshTrace;          /* Trace the SSH setup traffic */
  int fSshClient;         /* HTTP client flags for SSH client */
  char *zSshCmd;          /* SSH command string */
  int fNoSync;            /* Do not do an autosync ever.  --nosync */
  char *zPath;            /* Name of webpage being served */
  char *zExtra;           /* Extra path information past the webpage name */







>







137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
  char *zLocalRoot;       /* The directory holding the  local database */
  int minPrefix;          /* Number of digits needed for a distinct UUID */
  int fSqlTrace;          /* True if --sqltrace flag is present */
  int fSqlStats;          /* True if --sqltrace or --sqlstats are present */
  int fSqlPrint;          /* True if -sqlprint flag is present */
  int fQuiet;             /* True if -quiet flag is present */
  int fHttpTrace;         /* Trace outbound HTTP requests */
  int fUseHttpAuth;       /* True if user requests HTTP Authorization */
  int fSystemTrace;       /* Trace calls to fossil_system(), --systemtrace */
  int fSshTrace;          /* Trace the SSH setup traffic */
  int fSshClient;         /* HTTP client flags for SSH client */
  char *zSshCmd;          /* SSH command string */
  int fNoSync;            /* Do not do an autosync ever.  --nosync */
  char *zPath;            /* Name of webpage being served */
  char *zExtra;           /* Extra path information past the webpage name */
Changes to src/sync.c.
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
** This routine processes the command-line argument for push, pull,
** and sync.  If a command-line argument is given, that is the URL
** of a server to sync against.  If no argument is given, use the
** most recently synced URL.  Remember the current URL for next time.
*/
static void process_sync_args(unsigned *pConfigFlags, unsigned *pSyncFlags){
  const char *zUrl = 0;
  int fUseHttpAuth;           /* Use HTTP auth if requested by user */
  unsigned configSync = 0;
  unsigned urlFlags = URL_REMEMBER | URL_PROMPT_PW;
  int urlOptional = 0;
  if( find_option("autourl",0,0)!=0 ){
    urlOptional = 1;
    urlFlags = 0;
  }
  fUseHttpAuth = find_option("httpauth",0,0)!=0;
  if( find_option("once",0,0)!=0 ) urlFlags &= ~URL_REMEMBER;
  if( find_option("private",0,0)!=0 ){
    *pSyncFlags |= SYNC_PRIVATE;
  }
  if( find_option("verbose","v",0)!=0 ){
    *pSyncFlags |= SYNC_VERBOSE;
  }







<







|







81
82
83
84
85
86
87

88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
** This routine processes the command-line argument for push, pull,
** and sync.  If a command-line argument is given, that is the URL
** of a server to sync against.  If no argument is given, use the
** most recently synced URL.  Remember the current URL for next time.
*/
static void process_sync_args(unsigned *pConfigFlags, unsigned *pSyncFlags){
  const char *zUrl = 0;

  unsigned configSync = 0;
  unsigned urlFlags = URL_REMEMBER | URL_PROMPT_PW;
  int urlOptional = 0;
  if( find_option("autourl",0,0)!=0 ){
    urlOptional = 1;
    urlFlags = 0;
  }
  g.fUseHttpAuth = find_option("httpauth",0,0)!=0;
  if( find_option("once",0,0)!=0 ) urlFlags &= ~URL_REMEMBER;
  if( find_option("private",0,0)!=0 ){
    *pSyncFlags |= SYNC_PRIVATE;
  }
  if( find_option("verbose","v",0)!=0 ){
    *pSyncFlags |= SYNC_VERBOSE;
  }
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
  }else if( g.argc==3 ){
    zUrl = g.argv[2];
  }
  if( urlFlags & URL_REMEMBER ){
    clone_ssh_db_set_options();
  }
  url_parse(zUrl, urlFlags);
  remember_http_auth(fUseHttpAuth,zUrl);
  url_remember();
  if( g.urlProtocol==0 ){
    if( urlOptional ) fossil_exit(0);
    usage("URL");
  }
  user_select();
  if( g.argc==2 ){







|







115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  }else if( g.argc==3 ){
    zUrl = g.argv[2];
  }
  if( urlFlags & URL_REMEMBER ){
    clone_ssh_db_set_options();
  }
  url_parse(zUrl, urlFlags);
  remember_or_get_http_auth(urlFlags & URL_REMEMBER, zUrl);
  url_remember();
  if( g.urlProtocol==0 ){
    if( urlOptional ) fossil_exit(0);
    usage("URL");
  }
  user_select();
  if( g.argc==2 ){