- return (0);
-}
-
-/*
- * Returns the stream id for this stream. This is just the local
- * port.
- */
-static int
-krb5_stream_id(s)
- void *s;
-{
- struct krb5_stream *ks = s;
-
- assert(ks != NULL);
-
- return (ks->handle);
-}
-
-/*
- * Write a chunk of data to a stream. Blocks until completion.
- */
-static int
-krb5_stream_write(s, buf, size)
- void *s;
- const void *buf;
- size_t size;
-{
- struct krb5_stream *ks = s;
- gss_buffer_desc tok;
-#ifdef AMANDA_KRB5_ENCRYPT
- gss_buffer_desc enctok;
- OM_uint32 min_stat;
-#endif
- int rc;
-
- assert(ks != NULL);
-
- k5printf(("krb5: stream_write: writing %d bytes to %s:%d\n", size,
- ks->kc->hostname, ks->handle));
-
- tok.length = size;
- tok.value = (void *)buf; /* safe to discard const */
-#ifdef AMANDA_KRB5_ENCRYPT
- if (kencrypt(ks, &tok, &enctok) < 0)
- return (-1);
- rc = send_token(ks->kc, ks->handle, &enctok);
-#else
- rc = send_token(ks->kc, ks->handle, &tok);
-#endif
- if (rc < 0)
- security_stream_seterror(&ks->secstr, ks->kc->errmsg);
-#ifdef AMANDA_KRB5_ENCRYPT
- gss_release_buffer(&min_stat, &enctok);
-#endif
- return (rc);
-}
-
-/*
- * Submit a request to read some data. Calls back with the given
- * function and arg when completed.
- */
-static void
-krb5_stream_read(s, fn, arg)
- void *s, *arg;
- void (*fn) P((void *, void *, int));
-{
- struct krb5_stream *ks = s;
-
- assert(ks != NULL);
-
- /*
- * Only one read request can be active per stream.
- */
- ks->fn = fn;
- ks->arg = arg;
-
- /*
- * First see if there's any queued frames for this stream.
- * If so, we're done.
- */
- if (conn_run_frameq(ks->kc, ks) > 0)
- return;
-
- if (ks->ev_read == NULL) {
- ks->ev_read = event_register((event_id_t)ks->kc, EV_WAIT,
- stream_read_callback, ks);
- conn_read(ks->kc);
- }
-}
-
-/*
- * Cancel a previous stream read request. It's ok if we didn't have a read
- * scheduled.
- */
-static void
-krb5_stream_read_cancel(s)
- void *s;
-{
- struct krb5_stream *ks = s;
-
- assert(ks != NULL);
-
- if (ks->ev_read != NULL) {
- event_release(ks->ev_read);
- ks->ev_read = NULL;
- conn_read_cancel(ks->kc);
- }
-}
-
-/*
- * Callback for krb5_stream_read
- */
-static void
-stream_read_callback(arg)
- void *arg;
-{
- struct krb5_stream *ks = arg;
-
- assert(ks != NULL);
-
- k5printf(("krb5: stream_read_callback: handle %d\n", ks->handle));
-
- conn_run_frameq(ks->kc, ks);
-}
-
-/*
- * Run down a list of queued frames for a krb5_conn, and if we find one
- * that matches the passed handle, fire the read event. Only
- * process one frame.
- *
- * Returns 1 if a frame was found and processed.
- */
-static int
-conn_run_frameq(kc, ks)
- struct krb5_conn *kc;
- struct krb5_stream *ks;
-{
- struct krb5_frame *kf, *nextkf;
- gss_buffer_desc *enctok, *dectok;
-#ifdef AMANDA_KRB5_ENCRYPT
- OM_uint32 min_stat;
- gss_buffer_desc tok;
-#endif
-
- /*
- * Iterate through all of the frames in the queue. If one
- * is for us, process it. If we hit an EOF frame, shut down.
- * Stop after processing one frame, because we are only supposed
- * to return one read request.
- */
- for (kf = TAILQ_FIRST(&kc->frameq); kf != NULL; kf = nextkf) {
- nextkf = TAILQ_NEXT(kf, tq);
-
- if (kf->handle != ks->handle && kf->handle != H_EOF) {
- k5printf(("krb5: conn_frameq_run: not for us (handle %d)\n",
- kf->handle));
- continue;
- }
- /*
- * We want all listeners to see the EOF, so never remove it.
- * It will get cleaned up when the connection is closed
- * in conn_put().
- */
- if (kf->handle != H_EOF)
- TAILQ_REMOVE(&kc->frameq, kf, tq);
-
- /*
- * Remove the event first, and then call the callback.
- * We remove it first because we don't want to get in their
- * way if they reschedule it.
- */
- krb5_stream_read_cancel(ks);
-
- enctok = &kf->tok;
-
- if (enctok->length == 0) {
- assert(kf->handle == H_EOF);
- k5printf(("krb5: stream_read_callback: EOF\n"));
- (*ks->fn)(ks->arg, NULL, 0);
- return (1); /* stop after EOF */
- }
-
-#ifdef AMANDA_KRB5_ENCRYPT
- dectok = &tok;
- if (kdecrypt(ks, enctok, &tok) < 0) {
- k5printf(("krb5: stream_read_callback: kdecrypt error\n"));
- (*ks->fn)(ks->arg, NULL, -1);
- } else
-#else
- dectok = enctok;
-#endif
- {
- k5printf(("krb5: stream_read_callback: read %d bytes from %s:%d\n",
- dectok->length, ks->kc->hostname, ks->handle));
- (*ks->fn)(ks->arg, dectok->value, dectok->length);
-#ifdef AMANDA_KRB5_ENCRYPT
- gss_release_buffer(&min_stat, dectok);
-#endif
- }
- amfree(enctok->value);
- amfree(kf);
- return (1); /* stop after one frame */
- }
- return (0);
-}
-
-/*
- * The callback for the netfd for the event handler
- * Determines if this packet is for this security handle,
- * and does the real callback if so.
- */
-static void
-conn_read_callback(cookie)
- void *cookie;
-{
- struct krb5_conn *kc = cookie;
- struct krb5_handle *kh;
- struct krb5_frame *kf;
- pkt_t pkt;
- gss_buffer_desc *dectok;
- int rc;
-#ifdef AMANDA_KRB5_ENCRYPT
- gss_buffer_desc tok;
- OM_uint32 min_stat;
-#endif
-
- assert(cookie != NULL);
-
- k5printf(("krb5: conn_read_callback\n"));
-
- kf = alloc(sizeof(*kf));
- TAILQ_INSERT_TAIL(&kc->frameq, kf, tq);
-
- /* Read the data off the wire. If we get errors, shut down. */
- rc = recv_token(kc, &kf->handle, &kf->tok, 5);
- k5printf(("krb5: conn_read_callback: recv_token returned %d handle = %d\n",
- rc, kf->handle));
- if (rc <= 0) {
- kf->tok.value = NULL;
- kf->tok.length = 0;
- kf->handle = H_EOF;
- rc = event_wakeup((event_id_t)kc);
- k5printf(("krb5: conn_read_callback: event_wakeup return %d\n", rc));
- return;
- }
-
- /* If there are events waiting on this handle, we're done */
- rc = event_wakeup((event_id_t)kc);
- k5printf(("krb5: conn_read_callback: event_wakeup return %d\n", rc));
- if (rc > 0)
- return;
-
- /*
- * If there is no accept fn registered, then just leave the
- * packet queued. The caller may register a function later.
- */
- if (accept_fn == NULL) {
- k5printf(("krb5: no accept_fn so leaving packet queued.\n"));
- return;
- }
-
- kh = alloc(sizeof(*kh));
- security_handleinit(&kh->sech, &krb5_security_driver);
- kh->hostname = stralloc(kc->hostname);
- kh->ks = krb5_stream_client(kh, kf->handle);
- kh->ev_wait = NULL;
- kh->ev_timeout = NULL;
-
- TAILQ_REMOVE(&kc->frameq, kf, tq);
- k5printf(("krb5: new connection\n"));
-#ifdef AMANDA_KRB5_ENCRYPT
- dectok = &tok;
- rc = kdecrypt(kh->ks, &kf->tok, dectok);
-#else
- dectok = &kf->tok;
-#endif
-
-#ifdef AMANDA_KRB5_ENCRYPT
- if (rc < 0) {
- security_seterror(&kh->sech, security_geterror(&kh->ks->secstr));
- (*accept_fn)(&kh->sech, NULL);
- } else
-#endif
- {
- parse_pkt(&pkt, dectok->value, dectok->length);
-#ifdef AMANDA_KRB5_ENCRYPT
- gss_release_buffer(&min_stat, dectok);
-#endif
- (*accept_fn)(&kh->sech, &pkt);
- }
- amfree(kf->tok.value);
- amfree(kf);
-
- /*
- * We can only accept one connection per process, since we're tcp
- * based and run out of inetd. So, delete our accept reference once
- * we've gotten the first connection.
- */
-
- /*
- * [XXX] actually, the protocol has been changed to have multiple
- * requests in one session be possible. By not resetting accept_fn,
- * this will caused them to be properly processed. this needs to be
- * addressed in a much cleaner way.
- */
- if (accept_fn != NULL)
- conn_put(kc);
- /* accept_fn = NULL; */
-}
-
-/*