aboutsummaryrefslogtreecommitdiff
path: root/lib/security.c
diff options
context:
space:
mode:
authorJulien Chaffraix <julien.chaffraix@gmail.com>2010-09-12 15:41:44 -0700
committerDaniel Stenberg <daniel@haxx.se>2010-09-22 23:34:36 +0200
commitd23c59ecfc3d5a6b922a8d94a70c783d0fc69c05 (patch)
tree04920a5bf15ac9cac3f5d727015d9e38964aa16f /lib/security.c
parent1d95a48fe9b8a8ee80c820130291d38df698ade8 (diff)
security.c: Curl_sec_set_protection_level tweaking
- Removed sec_prot_internal as it is now inlined in the function (this removed a redundant check). - Changed the prototype to return an error code. - Updated the method to use the new ftp_send_command function. - Added a level_to_char helper method to avoid relying on the compiler's bound checks. This default to the maximum security we have in case of a wrong input.
Diffstat (limited to 'lib/security.c')
-rw-r--r--lib/security.c93
1 files changed, 57 insertions, 36 deletions
diff --git a/lib/security.c b/lib/security.c
index d4bb0b379..ca74ec54f 100644
--- a/lib/security.c
+++ b/lib/security.c
@@ -91,6 +91,29 @@ name_to_level(const char *name)
return (enum protection_level)-1;
}
+/* Convert a protocol |level| to its char representation.
+ We take an int to catch programming mistakes. */
+static char level_to_char(int level) {
+ switch(level) {
+ case prot_clear:
+ return 'C';
+ case prot_safe:
+ return 'S';
+ case prot_confidential:
+ return 'E';
+ case prot_private:
+ return 'P';
+ case prot_cmd:
+ /* Fall through */
+ default:
+ /* Those 2 cases should not be reached! */
+ break;
+ }
+ DEBUGASSERT(0);
+ /* Default to the most secure alternative. */
+ return 'P';
+}
+
static const struct Curl_sec_client_mech * const mechs[] = {
#if defined(HAVE_GSSAPI)
&Curl_krb5_client_mech,
@@ -369,64 +392,62 @@ Curl_set_command_prot(struct connectdata *conn, enum protection_level level)
return old;
}
-static int
-sec_prot_internal(struct connectdata *conn, int level)
+/* FIXME: The error code returned here is never checked. */
+int Curl_sec_set_protection_level(struct connectdata *conn)
{
- char *p;
- unsigned int s = 1048576;
- ssize_t nread;
+ int code;
+ char* pbsz;
+ static unsigned int buffer_size = 1 << 20; /* 1048576 */
+ enum protection_level level = conn->request_data_prot;
- if(!conn->sec_complete){
- infof(conn->data, "No security data exchange has taken place.\n");
+ if(!conn->sec_complete) {
+ infof(conn->data, "Trying to change the protection level after the"
+ "completion of the data exchange.");
return -1;
}
- if(level){
- int code;
- if(Curl_ftpsendf(conn, "PBSZ %u", s))
- return -1;
+ /* Bail out if we try to set up the same level */
+ if(conn->data_prot == level)
+ return 0;
- if(Curl_GetFTPResponse(&nread, conn, &code))
+ if(level) {
+ code = ftp_send_command(conn, "PSBZ %u", buffer_size);
+ if(code < 0)
return -1;
- if(code/100 != 2){
- failf(conn->data, "Failed to set protection buffer size.");
+ if(code/100 != 2) {
+ failf(conn->data, "Failed to set the protection's buffer size.");
return -1;
}
- conn->buffer_size = s;
-
- p = strstr(conn->data->state.buffer, "PBSZ=");
- if(p)
- sscanf(p, "PBSZ=%u", &s);
- if(s < conn->buffer_size)
- conn->buffer_size = s;
+ conn->buffer_size = buffer_size;
+
+ pbsz = strstr(conn->data->state.buffer, "PBSZ=");
+ if(pbsz) {
+ /* FIXME: Checks for errors in sscanf? */
+ sscanf(pbsz, "PBSZ=%u", &buffer_size);
+ if(buffer_size < conn->buffer_size)
+ conn->buffer_size = buffer_size;
+ }
}
- if(Curl_ftpsendf(conn, "PROT %c", level["CSEP"]))
- return -1;
+ /* Now try to negiociate the protection level. */
+ code = ftp_send_command(conn, "PROT %c", level_to_char(level));
- if(Curl_GetFTPResponse(&nread, conn, NULL))
+ if(code < 0)
return -1;
- if(conn->data->state.buffer[0] != '2'){
- failf(conn->data, "Failed to set protection level.");
+ if(code/100 != 2) {
+ failf(conn->data, "Failed to set the protection level.");
return -1;
}
- conn->data_prot = (enum protection_level)level;
+ conn->data_prot = level;
if(level == prot_private)
- conn->command_prot = (enum protection_level)level;
- return 0;
-}
+ conn->command_prot = level;
-void
-Curl_sec_set_protection_level(struct connectdata *conn)
-{
- if(conn->sec_complete && conn->data_prot != conn->request_data_prot)
- sec_prot_internal(conn, conn->request_data_prot);
+ return 0;
}
-
int
Curl_sec_request_prot(struct connectdata *conn, const char *level)
{