s4:heimdal: import lorikeet-heimdal-201107150856 (commit 48936803fae4a2fb362c79365d31...
[samba.git] / source4 / heimdal / lib / krb5 / store.c
index 0dedba3d72bf49d569c025f305084893e06fe178..3aeb8d6281443e6253ebd276a6f7752a74f9de43 100644 (file)
@@ -119,6 +119,41 @@ krb5_storage_get_byteorder(krb5_storage *sp)
     return sp->flags & KRB5_STORAGE_BYTEORDER_MASK;
 }
 
+/**
+ * Set the max alloc value
+ *
+ * @param sp the storage buffer set the max allow for
+ * @param size maximum size to allocate, use 0 to remove limit
+ *
+ * @ingroup krb5_storage
+ */
+
+KRB5_LIB_FUNCTION void KRB5_LIB_CALL
+krb5_storage_set_max_alloc(krb5_storage *sp, size_t size)
+{
+    sp->max_alloc = size;
+}
+
+/* don't allocate unresonable amount of memory */
+static krb5_error_code
+size_too_large(krb5_storage *sp, size_t size)
+{
+    if (sp->max_alloc && sp->max_alloc < size)
+       return HEIM_ERR_TOO_BIG;
+    return 0;
+}
+
+static krb5_error_code
+size_too_large_num(krb5_storage *sp, size_t count, size_t size)
+{
+    if (sp->max_alloc == 0 || size == 0)
+       return 0;
+    size = sp->max_alloc / size;
+    if (size < count)
+       return HEIM_ERR_TOO_BIG;
+    return 0;
+}
+
 /**
  * Seek to a new offset.
  *
@@ -262,10 +297,11 @@ krb5_storage_to_data(krb5_storage *sp, krb5_data *data)
     pos = sp->seek(sp, 0, SEEK_CUR);
     if (pos < 0)
        return HEIM_ERR_NOT_SEEKABLE;
-    size = (size_t)sp->seek(sp, 0, SEEK_END);
-    if (size > (size_t)-1)
-       return HEIM_ERR_TOO_BIG;
-    ret = krb5_data_alloc (data, size);
+    size = sp->seek(sp, 0, SEEK_END);
+    ret = size_too_large(sp, size);
+    if (ret)
+       return ret;
+    ret = krb5_data_alloc(data, size);
     if (ret) {
        sp->seek(sp, pos, SEEK_SET);
        return ret;
@@ -290,8 +326,10 @@ krb5_store_int(krb5_storage *sp,
        return EINVAL;
     _krb5_put_int(v, value, len);
     ret = sp->store(sp, v, len);
-    if (ret != len)
-       return (ret<0)?errno:sp->eof_code;
+    if (ret < 0)
+       return errno;
+    if ((size_t)ret != len)
+       return sp->eof_code;
     return 0;
 }
 
@@ -346,8 +384,10 @@ krb5_ret_int(krb5_storage *sp,
     unsigned char v[4];
     unsigned long w;
     ret = sp->fetch(sp, v, len);
-    if(ret != len)
-       return (ret<0)?errno:sp->eof_code;
+    if (ret < 0)
+       return errno;
+    if ((size_t)ret != len)
+       return sp->eof_code;
     _krb5_get_int(v, &w, len);
     *value = w;
     return 0;
@@ -612,11 +652,10 @@ krb5_store_data(krb5_storage *sp,
     if(ret < 0)
        return ret;
     ret = sp->store(sp, data.data, data.length);
-    if(ret != data.length){
-       if(ret < 0)
-           return errno;
+    if(ret < 0)
+       return errno;
+    if((size_t)ret != data.length)
        return sp->eof_code;
-    }
     return 0;
 }
 
@@ -641,6 +680,9 @@ krb5_ret_data(krb5_storage *sp,
     ret = krb5_ret_int32(sp, &size);
     if(ret)
        return ret;
+    ret = size_too_large(sp, size);
+    if (ret)
+       return ret;
     ret = krb5_data_alloc (data, size);
     if (ret)
        return ret;
@@ -722,12 +764,10 @@ krb5_store_stringz(krb5_storage *sp, const char *s)
     ssize_t ret;
 
     ret = sp->store(sp, s, len);
-    if(ret != len) {
-       if(ret < 0)
-           return ret;
-       else
-           return sp->eof_code;
-    }
+    if(ret < 0)
+       return ret;
+    if((size_t)ret != len)
+       return sp->eof_code;
     return 0;
 }
 
@@ -755,6 +795,9 @@ krb5_ret_stringz(krb5_storage *sp,
        char *tmp;
 
        len++;
+       ret = size_too_large(sp, len);
+       if (ret)
+           break;
        tmp = realloc (s, len);
        if (tmp == NULL) {
            free (s);
@@ -782,12 +825,10 @@ krb5_store_stringnl(krb5_storage *sp, const char *s)
     ssize_t ret;
 
     ret = sp->store(sp, s, len);
-    if(ret != len) {
-       if(ret < 0)
-           return ret;
-       else
-           return sp->eof_code;
-    }
+    if(ret < 0)
+       return ret;
+    if((size_t)ret != len)
+       return sp->eof_code;
     ret = sp->store(sp, "\n", 1);
     if(ret != 1) {
        if(ret < 0)
@@ -823,6 +864,9 @@ krb5_ret_stringnl(krb5_storage *sp,
        }
 
        len++;
+       ret = size_too_large(sp, len);
+       if (ret)
+           break;
        tmp = realloc (s, len);
        if (tmp == NULL) {
            free (s);
@@ -860,7 +904,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_store_principal(krb5_storage *sp,
                     krb5_const_principal p)
 {
-    int i;
+    size_t i;
     int ret;
 
     if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) {
@@ -923,6 +967,11 @@ krb5_ret_principal(krb5_storage *sp,
        free(p);
        return EINVAL;
     }
+    ret = size_too_large_num(sp, ncomp, sizeof(p->name.name_string.val[0]));
+    if (ret) {
+       free(p);
+       return ret;
+    }
     p->name.name_type = type;
     p->name.name_string.len = ncomp;
     ret = krb5_ret_string(sp, &p->realm);
@@ -930,7 +979,7 @@ krb5_ret_principal(krb5_storage *sp,
        free(p);
        return ret;
     }
-    p->name.name_string.val = calloc(ncomp, sizeof(*p->name.name_string.val));
+    p->name.name_string.val = calloc(ncomp, sizeof(p->name.name_string.val[0]));
     if(p->name.name_string.val == NULL && ncomp != 0){
        free(p->realm);
        free(p);
@@ -1122,7 +1171,7 @@ krb5_ret_address(krb5_storage *sp, krb5_address *adr)
 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_store_addrs(krb5_storage *sp, krb5_addresses p)
 {
-    int i;
+    size_t i;
     int ret;
     ret = krb5_store_int32(sp, p.len);
     if(ret) return ret;
@@ -1147,12 +1196,14 @@ krb5_store_addrs(krb5_storage *sp, krb5_addresses p)
 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr)
 {
-    int i;
+    size_t i;
     int ret;
     int32_t tmp;
 
     ret = krb5_ret_int32(sp, &tmp);
     if(ret) return ret;
+    ret = size_too_large_num(sp, tmp, sizeof(adr->val[0]));
+    if (ret) return ret;
     adr->len = tmp;
     ALLOC(adr->val, adr->len);
     if (adr->val == NULL && adr->len != 0)
@@ -1179,7 +1230,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_store_authdata(krb5_storage *sp, krb5_authdata auth)
 {
     krb5_error_code ret;
-    int i;
+    size_t i;
     ret = krb5_store_int32(sp, auth.len);
     if(ret) return ret;
     for(i = 0; i < auth.len; i++){
@@ -1211,6 +1262,8 @@ krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth)
     int i;
     ret = krb5_ret_int32(sp, &tmp);
     if(ret) return ret;
+    ret = size_too_large_num(sp, tmp, sizeof(auth->val[0]));
+    if (ret) return ret;
     ALLOC_SEQ(auth, tmp);
     if (auth->val == NULL && tmp != 0)
        return ENOMEM;
@@ -1345,7 +1398,7 @@ krb5_ret_creds(krb5_storage *sp, krb5_creds *creds)
     ret = krb5_ret_data (sp,  &creds->second_ticket);
 cleanup:
     if(ret) {
-#if 0  
+#if 0
        krb5_free_cred_contents(context, creds); /* XXX */
 #endif
     }
@@ -1530,7 +1583,7 @@ krb5_ret_creds_tag(krb5_storage *sp,
 
 cleanup:
     if(ret) {
-#if 0  
+#if 0
        krb5_free_cred_contents(context, creds); /* XXX */
 #endif
     }