]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
r23926: implement output buffer handling for the SASL write wrapper
authorStefan Metzmacher <metze@samba.org>
Tue, 17 Jul 2007 11:14:42 +0000 (11:14 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:28:45 +0000 (12:28 -0500)
metze

source/include/ads.h
source/libads/sasl_wrapping.c

index 8404ad907b50477ed20b4633c46e623b1021a480..c103c3a43ee13db36199e8786de54a3135a10402 100644 (file)
@@ -34,7 +34,7 @@ struct ads_struct;
 
 struct ads_saslwrap_ops {
        const char *name;
-       ADS_STATUS (*wrap)(struct ads_struct *);
+       ADS_STATUS (*wrap)(struct ads_struct *, uint8 *buf, uint32 len);
        ADS_STATUS (*unwrap)(struct ads_struct *);
        ADS_STATUS (*disconnect)(struct ads_struct *);
 };
@@ -101,10 +101,10 @@ typedef struct ads_struct {
                } in;
                struct {
                        uint32 ofs;
-                       uint32 needed;
                        uint32 left;
                        uint32 max;
                        uint32 min;
+                       uint32 sig_size;
                        uint32 size;
                        uint8 *buf;
                } out;
index 9617961969fd07f5d4c40b02bc301aa9c87eda63..419557a7bb2b18b55e94fb03e20b5c281991686e 100644 (file)
@@ -170,9 +170,75 @@ eagain:
        return -1;
 }
 
+static ber_slen_t ads_saslwrap_prepare_outbuf(ADS_STRUCT *ads, uint32 len)
+{
+       ads->ldap.out.ofs       = 4;
+       ads->ldap.out.left      = 4;
+       ads->ldap.out.size      = 4 + ads->ldap.out.sig_size + len;
+       ads->ldap.out.buf       = talloc_array(ads->ldap.mem_ctx,
+                                              uint8, ads->ldap.out.size);
+       if (!ads->ldap.out.buf) {
+               return -1;
+       }
+
+       return 0;
+}
+
+static void ads_saslwrap_shrink_outbuf(ADS_STRUCT *ads)
+{
+       talloc_free(ads->ldap.out.buf);
+
+       ads->ldap.out.buf       = NULL;
+       ads->ldap.out.size      = 0;
+       ads->ldap.out.ofs       = 0;
+       ads->ldap.out.left      = 0;
+}
+
 static ber_slen_t ads_saslwrap_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
 {
-       return LBER_SBIOD_WRITE_NEXT(sbiod, buf, len);
+       ADS_STRUCT *ads = (ADS_STRUCT *)sbiod->sbiod_pvt;
+       ber_slen_t ret, rlen;
+
+       /* if the buffer is empty, we need to wrap in incoming buffer */
+       if (ads->ldap.out.left == 0) {
+               ADS_STATUS status;
+
+               if (len == 0) {
+                       errno = EINVAL;
+                       return -1;
+               }
+
+               rlen = MIN(len, ads->ldap.out.max);
+
+               ret = ads_saslwrap_prepare_outbuf(ads, rlen);
+               if (ret < 0) return ret;
+               
+               status = ads->ldap.wrap_ops->wrap(ads, buf, rlen);
+               if (!ADS_ERR_OK(status)) {
+                       errno = EACCES;
+                       return -1;
+               }
+
+               RSIVAL(ads->ldap.out.buf, 0, ads->ldap.out.size - 4);
+       } else {
+               rlen = -1;
+       }
+
+       ret = LBER_SBIOD_WRITE_NEXT(sbiod,
+                                   ads->ldap.out.buf + ads->ldap.out.ofs,
+                                   ads->ldap.out.left);
+       if (ret < 0) return ret;
+       ads->ldap.out.ofs += ret;
+       ads->ldap.out.left -= ret;
+
+       if (ads->ldap.out.left == 0) {
+               ads_saslwrap_shrink_outbuf(ads);
+       }
+
+       if (rlen > 0) return rlen;
+
+       errno = EAGAIN;
+       return -1;
 }
 
 static int ads_saslwrap_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg)