url: use same credentials on redirect

Previously it could lose the username and only use the password.

Added test 998 and 999 to verify.

Reported-by: Tobias Bora
Fixes #15262
Closes #15282
This commit is contained in:
Daniel Stenberg 2024-10-12 23:54:39 +02:00
parent eb77297ccc
commit 9bee39bfed
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
6 changed files with 257 additions and 73 deletions

View File

@ -679,6 +679,9 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
return CURLE_OUT_OF_MEMORY;
}
if(data->set.str[STRING_USERNAME] ||
data->set.str[STRING_PASSWORD])
data->state.creds_from = CREDS_OPTION;
if(!result)
result = Curl_setstropt(&data->state.aptr.user,
data->set.str[STRING_USERNAME]);

View File

@ -1860,10 +1860,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
return result;
/*
* username and password set with their own options override the
* credentials possibly set in the URL.
* username and password set with their own options override the credentials
* possibly set in the URL, but netrc does not.
*/
if(!data->set.str[STRING_PASSWORD]) {
if(!data->state.aptr.passwd || (data->state.creds_from != CREDS_OPTION)) {
uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
if(!uc) {
char *decoded;
@ -1876,12 +1876,13 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
result = Curl_setstropt(&data->state.aptr.passwd, decoded);
if(result)
return result;
data->state.creds_from = CREDS_URL;
}
else if(uc != CURLUE_NO_PASSWORD)
return Curl_uc_to_curlcode(uc);
}
if(!data->set.str[STRING_USERNAME]) {
if(!data->state.aptr.user || (data->state.creds_from != CREDS_OPTION)) {
/* we do not use the URL API's URL decoder option here since it rejects
control codes and we want to allow them for some schemes in the user
and password fields */
@ -1895,13 +1896,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
return result;
conn->user = decoded;
result = Curl_setstropt(&data->state.aptr.user, decoded);
data->state.creds_from = CREDS_URL;
}
else if(uc != CURLUE_NO_USER)
return Curl_uc_to_curlcode(uc);
else if(data->state.aptr.passwd) {
/* no user was set but a password, set a blank user */
result = Curl_setstropt(&data->state.aptr.user, "");
}
if(result)
return result;
}
@ -2685,7 +2683,8 @@ static CURLcode override_login(struct Curl_easy *data,
int ret;
bool url_provided = FALSE;
if(data->state.aptr.user) {
if(data->state.aptr.user &&
(data->state.creds_from != CREDS_NETRC)) {
/* there was a username in the URL. Use the URL decoded version */
userp = &data->state.aptr.user;
url_provided = TRUE;
@ -2733,6 +2732,7 @@ static CURLcode override_login(struct Curl_easy *data,
result = Curl_setstropt(&data->state.aptr.user, *userp);
if(result)
return result;
data->state.creds_from = CREDS_NETRC;
}
}
if(data->state.aptr.user) {
@ -2750,6 +2750,7 @@ static CURLcode override_login(struct Curl_easy *data,
CURLcode result = Curl_setstropt(&data->state.aptr.passwd, *passwdp);
if(result)
return result;
data->state.creds_from = CREDS_NETRC;
}
if(data->state.aptr.passwd) {
uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD,

View File

@ -1206,6 +1206,11 @@ struct urlpieces {
char *query;
};
#define CREDS_NONE 0
#define CREDS_URL 1 /* from URL */
#define CREDS_OPTION 2 /* set with a CURLOPT_ */
#define CREDS_NETRC 3 /* found in netrc */
struct UrlState {
/* buffers to store authentication data in, as parsed from input options */
struct curltime keeps_speed; /* for the progress meter really */
@ -1344,7 +1349,6 @@ struct UrlState {
char *proxypasswd;
#endif
} aptr;
unsigned char httpwant; /* when non-zero, a specific HTTP version requested
to be used in the library's request(s) */
unsigned char httpversion; /* the lowest HTTP version*10 reported by any
@ -1354,6 +1358,9 @@ struct UrlState {
unsigned char select_bits; /* != 0 -> bitmask of socket events for this
transfer overriding anything the socket may
report */
unsigned int creds_from:2; /* where is the server credentials originating
from, see the CREDS_* defines above */
/* when curl_easy_perform() is called, the multi handle is "owned" by
the easy handle so curl_easy_cleanup() on such an easy handle will
also close the multi handle! */

View File

@ -133,69 +133,69 @@ test961 test962 test963 test964 test965 test966 test967 test968 test969 \
test970 test971 test972 test973 test974 test975 test976 test977 test978 \
test979 test980 test981 test982 test983 test984 test985 test986 test987 \
test988 test989 test990 test991 test992 test993 test994 test995 test996 \
test997 \
test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \
test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
test1016 test1017 test1018 test1019 test1020 test1021 test1022 test1023 \
test1024 test1025 test1026 test1027 test1028 test1029 test1030 test1031 \
test1032 test1033 test1034 test1035 test1036 test1037 test1038 test1039 \
test1040 test1041 test1042 test1043 test1044 test1045 test1046 test1047 \
test1048 test1049 test1050 test1051 test1052 test1053 test1054 test1055 \
test1056 test1057 test1058 test1059 test1060 test1061 test1062 test1063 \
test1064 test1065 test1066 test1067 test1068 test1069 test1070 test1071 \
test1072 test1073 test1074 test1075 test1076 test1077 test1078 test1079 \
test1080 test1081 test1082 test1083 test1084 test1085 test1086 test1087 \
test1088 test1089 test1090 test1091 test1092 test1093 test1094 test1095 \
test1096 test1097 test1098 test1099 test1100 test1101 test1102 test1103 \
test1104 test1105 test1106 test1107 test1108 test1109 test1110 test1111 \
test1112 test1113 test1114 test1115 test1116 test1117 test1118 test1119 \
test1120 test1121 test1122 test1123 test1124 test1125 test1126 test1127 \
test1128 test1129 test1130 test1131 test1132 test1133 test1134 test1135 \
test1136 test1137 test1138 test1139 test1140 test1141 test1142 test1143 \
test1144 test1145 test1146 test1147 test1148 test1149 test1150 test1151 \
test1152 test1153 test1154 test1155 test1156 test1157 test1158 test1159 \
test1160 test1161 test1162 test1163 test1164 test1165 test1166 test1167 \
test1168 test1169 test1170 test1171 test1172 test1173 test1174 test1175 \
test1176 test1177 test1178 test1179 test1180 test1181 test1182 test1183 \
test1184 test1185 test1186 test1187 test1188 test1189 test1190 test1190 \
test1191 test1192 test1193 test1194 test1195 test1196 test1197 test1198 \
test1199 test1200 test1201 test1202 test1203 test1204 test1205 test1206 \
test1207 test1208 test1209 test1210 test1211 test1212 test1213 test1214 \
test1215 test1216 test1217 test1218 test1219 test1220 test1221 test1222 \
test1223 test1224 test1225 test1226 test1227 test1228 test1229 test1230 \
test1231 test1232 test1233 test1234 test1235 test1236 test1237 test1238 \
test1239 test1240 test1241 test1242 test1243 test1244 test1245 test1246 \
test1247 test1248 test1249 test1250 test1251 test1252 test1253 test1254 \
test1255 test1256 test1257 test1258 test1259 test1260 test1261 test1262 \
test1263 test1264 test1265 test1266 test1267 test1268 test1269 test1270 \
test1271 test1272 test1273 test1274 test1275 test1276 test1277 test1278 \
test1279 test1280 test1281 test1282 test1283 test1284 test1285 test1286 \
test1287 test1288 test1289 test1290 test1291 test1292 test1293 test1294 \
test1295 test1296 test1297 test1298 test1299 test1300 test1301 test1302 \
test1303 test1304 test1305 test1306 test1307 test1308 test1309 test1310 \
test1311 test1312 test1313 test1314 test1315 test1316 test1317 test1318 \
test1319 test1320 test1321 test1322 test1323 test1324 test1325 test1326 \
test1327 test1328 test1329 test1330 test1331 test1332 test1333 test1334 \
test1335 test1336 test1337 test1338 test1339 test1340 test1341 test1342 \
test1343 test1344 test1345 test1346 test1347 test1348 test1349 test1350 \
test1351 test1352 test1353 test1354 test1355 test1356 test1357 test1358 \
test1359 test1360 test1361 test1362 test1363 test1364 test1365 test1366 \
test1367 test1368 test1369 test1370 test1371 test1372 test1373 test1374 \
test1375 test1376 test1377 test1378 test1379 test1380 test1381 test1382 \
test1383 test1384 test1385 test1386 test1387 test1388 test1389 test1390 \
test1391 test1392 test1393 test1394 test1395 test1396 test1397 test1398 \
test1399 test1400 test1401 test1402 test1403 test1404 test1405 test1406 \
test1407 test1408 test1409 test1410 test1411 test1412 test1413 test1414 \
test1415 test1416 test1417 test1418 test1419 test1420 test1421 test1422 \
test1423 test1424 test1425 test1426 test1427 test1428 test1429 test1430 \
test1431 test1432 test1433 test1434 test1435 test1436 test1437 test1438 \
test1439 test1440 test1441 test1442 test1443 test1444 test1445 test1446 \
test1447 test1448 test1449 test1450 test1451 test1452 test1453 test1454 \
test1455 test1456 test1457 test1458 test1459 test1460 test1461 test1462 \
test1463 test1464 test1465 test1466 test1467 test1468 test1469 test1470 \
test1471 test1472 test1473 test1474 test1475 test1476 test1477 test1478 \
test1479 test1480 test1481 test1482 test1483 test1484 test1485 test1486 \
test1487 test1488 test1489 test1490 test1491 test1492 \
test997 test998 test999 test1000 test1001 test1002 test1003 test1004 \
test1005 test1006 test1007 test1008 test1009 test1010 test1011 test1012 \
test1013 test1014 test1015 test1016 test1017 test1018 test1019 test1020 \
test1021 test1022 test1023 test1024 test1025 test1026 test1027 test1028 \
test1029 test1030 test1031 test1032 test1033 test1034 test1035 test1036 \
test1037 test1038 test1039 test1040 test1041 test1042 test1043 test1044 \
test1045 test1046 test1047 test1048 test1049 test1050 test1051 test1052 \
test1053 test1054 test1055 test1056 test1057 test1058 test1059 test1060 \
test1061 test1062 test1063 test1064 test1065 test1066 test1067 test1068 \
test1069 test1070 test1071 test1072 test1073 test1074 test1075 test1076 \
test1077 test1078 test1079 test1080 test1081 test1082 test1083 test1084 \
test1085 test1086 test1087 test1088 test1089 test1090 test1091 test1092 \
test1093 test1094 test1095 test1096 test1097 test1098 test1099 test1100 \
test1101 test1102 test1103 test1104 test1105 test1106 test1107 test1108 \
test1109 test1110 test1111 test1112 test1113 test1114 test1115 test1116 \
test1117 test1118 test1119 test1120 test1121 test1122 test1123 test1124 \
test1125 test1126 test1127 test1128 test1129 test1130 test1131 test1132 \
test1133 test1134 test1135 test1136 test1137 test1138 test1139 test1140 \
test1141 test1142 test1143 test1144 test1145 test1146 test1147 test1148 \
test1149 test1150 test1151 test1152 test1153 test1154 test1155 test1156 \
test1157 test1158 test1159 test1160 test1161 test1162 test1163 test1164 \
test1165 test1166 test1167 test1168 test1169 test1170 test1171 test1172 \
test1173 test1174 test1175 test1176 test1177 test1178 test1179 test1180 \
test1181 test1182 test1183 test1184 test1185 test1186 test1187 test1188 \
test1189 test1190 test1190 test1191 test1192 test1193 test1194 test1195 \
test1196 test1197 test1198 test1199 test1200 test1201 test1202 test1203 \
test1204 test1205 test1206 test1207 test1208 test1209 test1210 test1211 \
test1212 test1213 test1214 test1215 test1216 test1217 test1218 test1219 \
test1220 test1221 test1222 test1223 test1224 test1225 test1226 test1227 \
test1228 test1229 test1230 test1231 test1232 test1233 test1234 test1235 \
test1236 test1237 test1238 test1239 test1240 test1241 test1242 test1243 \
test1244 test1245 test1246 test1247 test1248 test1249 test1250 test1251 \
test1252 test1253 test1254 test1255 test1256 test1257 test1258 test1259 \
test1260 test1261 test1262 test1263 test1264 test1265 test1266 test1267 \
test1268 test1269 test1270 test1271 test1272 test1273 test1274 test1275 \
test1276 test1277 test1278 test1279 test1280 test1281 test1282 test1283 \
test1284 test1285 test1286 test1287 test1288 test1289 test1290 test1291 \
test1292 test1293 test1294 test1295 test1296 test1297 test1298 test1299 \
test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 \
test1308 test1309 test1310 test1311 test1312 test1313 test1314 test1315 \
test1316 test1317 test1318 test1319 test1320 test1321 test1322 test1323 \
test1324 test1325 test1326 test1327 test1328 test1329 test1330 test1331 \
test1332 test1333 test1334 test1335 test1336 test1337 test1338 test1339 \
test1340 test1341 test1342 test1343 test1344 test1345 test1346 test1347 \
test1348 test1349 test1350 test1351 test1352 test1353 test1354 test1355 \
test1356 test1357 test1358 test1359 test1360 test1361 test1362 test1363 \
test1364 test1365 test1366 test1367 test1368 test1369 test1370 test1371 \
test1372 test1373 test1374 test1375 test1376 test1377 test1378 test1379 \
test1380 test1381 test1382 test1383 test1384 test1385 test1386 test1387 \
test1388 test1389 test1390 test1391 test1392 test1393 test1394 test1395 \
test1396 test1397 test1398 test1399 test1400 test1401 test1402 test1403 \
test1404 test1405 test1406 test1407 test1408 test1409 test1410 test1411 \
test1412 test1413 test1414 test1415 test1416 test1417 test1418 test1419 \
test1420 test1421 test1422 test1423 test1424 test1425 test1426 test1427 \
test1428 test1429 test1430 test1431 test1432 test1433 test1434 test1435 \
test1436 test1437 test1438 test1439 test1440 test1441 test1442 test1443 \
test1444 test1445 test1446 test1447 test1448 test1449 test1450 test1451 \
test1452 test1453 test1454 test1455 test1456 test1457 test1458 test1459 \
test1460 test1461 test1462 test1463 test1464 test1465 test1466 test1467 \
test1468 test1469 test1470 test1471 test1472 test1473 test1474 test1475 \
test1476 test1477 test1478 test1479 test1480 test1481 test1482 test1483 \
test1484 test1485 test1486 test1487 test1488 test1489 test1490 test1491 \
test1492 \
\
test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
test1508 test1509 test1510 test1511 test1512 test1513 test1514 test1515 \

92
tests/data/test998 Normal file
View File

@ -0,0 +1,92 @@
<testcase>
<info>
<keywords>
HTTP
--location-trusted
</keywords>
</info>
#
# Server-side
<reply>
<data>
HTTP/1.1 301 redirect
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Length: 0
Connection: close
Content-Type: text/html
Location: http://somewhere.else.example/a/path/%TESTNUMBER0002
</data>
<data2>
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Content-Length: 6
Content-Type: text/html
Funny-head: yesyes
-foo-
</data2>
<datacheck>
HTTP/1.1 301 redirect
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Length: 0
Connection: close
Content-Type: text/html
Location: http://somewhere.else.example/a/path/%TESTNUMBER0002
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Content-Length: 6
Content-Type: text/html
Funny-head: yesyes
-foo-
</datacheck>
</reply>
#
# Client-side
<client>
<features>
proxy
</features>
<server>
http
</server>
<name>
HTTP with auth in URL redirected to another host
</name>
<command>
-x %HOSTIP:%HTTPPORT http://alberto:einstein@somwhere.example/%TESTNUMBER --location-trusted
</command>
</client>
#
# Verify data after the test has been "shot"
<verify>
<strip>
QUIT
</strip>
<protocol>
GET http://somwhere.example/998 HTTP/1.1
Host: somwhere.example
Authorization: Basic YWxiZXJ0bzplaW5zdGVpbg==
User-Agent: curl/%VERSION
Accept: */*
Proxy-Connection: Keep-Alive
GET http://somewhere.else.example/a/path/9980002 HTTP/1.1
Host: somewhere.else.example
Authorization: Basic YWxiZXJ0bzplaW5zdGVpbg==
User-Agent: curl/%VERSION
Accept: */*
Proxy-Connection: Keep-Alive
</protocol>
</verify>
</testcase>

81
tests/data/test999 Normal file
View File

@ -0,0 +1,81 @@
<testcase>
<info>
<keywords>
HTTP
--location-trusted
</keywords>
</info>
#
# Server-side
<reply>
<data nocheck="yes">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Content-Length: 6
Content-Type: text/html
Funny-head: yesyes
-foo-
</data>
<datacheck>
HTTP/1.1 301 redirect
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Length: 0
Connection: close
Content-Type: text/html
Location: http://somewhere.else.example/a/path/%TESTNUMBER0002
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Content-Length: 6
Content-Type: text/html
Funny-head: yesyes
-foo-
</datacheck>
</reply>
#
# Client-side
<client>
<features>
proxy
</features>
<server>
http
</server>
<name>
HTTP with auth in first URL but not second
</name>
<command>
-x %HOSTIP:%HTTPPORT http://alberto:einstein@somwhere.example/%TESTNUMBER http://somewhere.else.example/%TESTNUMBER
</command>
</client>
#
# Verify data after the test has been "shot"
<verify>
<strip>
QUIT
</strip>
<protocol>
GET http://somwhere.example/%TESTNUMBER HTTP/1.1
Host: somwhere.example
Authorization: Basic YWxiZXJ0bzplaW5zdGVpbg==
User-Agent: curl/%VERSION
Accept: */*
Proxy-Connection: Keep-Alive
GET http://somewhere.else.example/%TESTNUMBER HTTP/1.1
Host: somewhere.else.example
User-Agent: curl/%VERSION
Accept: */*
Proxy-Connection: Keep-Alive
</protocol>
</verify>
</testcase>