File netatalk-CVE-2018-1160.patch of Package netatalk.27687
Index: netatalk-3.1.0/libatalk/dsi/dsi_opensess.c
===================================================================
--- netatalk-3.1.0.orig/libatalk/dsi/dsi_opensess.c 2013-10-28 14:43:14.000000000 +0100
+++ netatalk-3.1.0/libatalk/dsi/dsi_opensess.c 2018-12-18 12:08:37.344665536 +0100
@@ -19,8 +19,12 @@
/* OpenSession. set up the connection */
void dsi_opensession(DSI *dsi)
{
- uint32_t i = 0; /* this serves double duty. it must be 4-bytes long */
+ size_t i = 0;
+ uint32_t servquant;
+ uint32_t replcsize;
int offs;
+ uint8_t cmd;
+ size_t option_len;
if (setnonblock(dsi->socket, 1) < 0) {
LOG(log_error, logtype_dsi, "dsi_opensession: setnonblock: %s", strerror(errno));
@@ -28,17 +32,32 @@ void dsi_opensession(DSI *dsi)
}
/* parse options */
- while (i < dsi->cmdlen) {
- switch (dsi->commands[i++]) {
+ while (i + 1 < dsi->cmdlen) {
+ cmd = dsi->commands[i++];
+ option_len = dsi->commands[i++];
+
+ if (i + option_len > dsi->cmdlen) {
+ LOG(log_error, logtype_dsi, "option %"PRIu8" too large: %zu",
+ cmd, option_len);
+ exit(EXITERR_CLNT);
+ }
+
+ switch (cmd) {
case DSIOPT_ATTNQUANT:
- memcpy(&dsi->attn_quantum, dsi->commands + i + 1, dsi->commands[i]);
+ if (option_len != sizeof(dsi->attn_quantum)) {
+ LOG(log_error, logtype_dsi, "option %"PRIu8" bad length: %zu",
+ cmd, option_len);
+ exit(EXITERR_CLNT);
+ }
+ memcpy(&dsi->attn_quantum, &dsi->commands[i], option_len);
dsi->attn_quantum = ntohl(dsi->attn_quantum);
case DSIOPT_SERVQUANT: /* just ignore these */
default:
- i += dsi->commands[i] + 1; /* forward past length tag + length */
break;
}
+
+ i += option_len;
}
/* let the client know the server quantum. we don't use the
@@ -47,21 +66,21 @@ void dsi_opensession(DSI *dsi)
dsi->header.dsi_data.dsi_code = 0;
/* dsi->header.dsi_command = DSIFUNC_OPEN;*/
- dsi->cmdlen = 2 * (2 + sizeof(i)); /* length of data. dsi_send uses it. */
+ dsi->cmdlen = 2 * (2 + sizeof(uint32_t)); /* length of data. dsi_send uses it. */
/* DSI Option Server Request Quantum */
dsi->commands[0] = DSIOPT_SERVQUANT;
- dsi->commands[1] = sizeof(i);
- i = htonl(( dsi->server_quantum < DSI_SERVQUANT_MIN ||
+ dsi->commands[1] = sizeof(servquant);
+ servquant = htonl(( dsi->server_quantum < DSI_SERVQUANT_MIN ||
dsi->server_quantum > DSI_SERVQUANT_MAX ) ?
DSI_SERVQUANT_DEF : dsi->server_quantum);
- memcpy(dsi->commands + 2, &i, sizeof(i));
+ memcpy(dsi->commands + 2, &servquant, sizeof(servquant));
/* AFP replaycache size option */
- offs = 2 + sizeof(i);
+ offs = 2 + sizeof(replcsize);
dsi->commands[offs] = DSIOPT_REPLCSIZE;
- dsi->commands[offs+1] = sizeof(i);
- i = htonl(REPLAYCACHE_SIZE);
- memcpy(dsi->commands + offs + 2, &i, sizeof(i));
+ dsi->commands[offs+1] = sizeof(replcsize);
+ replcsize = htonl(REPLAYCACHE_SIZE);
+ memcpy(dsi->commands + offs + 2, &replcsize, sizeof(replcsize));
dsi_send(dsi);
}