commit - f9d09706c26867a700fc666e9809f029520f5848
commit + 0d6b67e271d1f497a862858fce73c5a9b430ef11
blob - 80fc725d32a21c67dbac7e260514e2a352c549cd
blob + 8aab8d4e3b63b817ca0ccd4dcfbf8160525c18f5
--- gotsh/gotsh.c
+++ gotsh/gotsh.c
/* Read session URL from gotwebd's auth socket and send it to the client. */
static const struct got_error *
-weblogin(int outfd, int sock, const char *hostname)
+weblogin(FILE *out, int sock, const char *hostname)
{
const struct got_error *err = NULL;
- char *url = NULL, *greeting = NULL;
- char buf[_POSIX_HOST_NAME_MAX + 2];
- size_t size, remain;
+ FILE *fp;
int ret;
+ char *line = NULL;
+ size_t linesize;
+ ssize_t linelen;
- if (hostname) {
- /*
- * Send the desired hostname to gotwebd.
- * gotwebd reads up to _POSIX_HOST_NAME_MAX + 1 bytes, terminated
- * by a linefeed, \n.
- */
- ret = snprintf(buf, sizeof(buf), "login %s\n", hostname);
- } else
- ret = snprintf(buf, sizeof(buf), "login\n");
- if (ret == -1)
- return got_error_from_errno("snprintf");
- if ((size_t)ret >= sizeof(buf))
- return got_error(GOT_ERR_NO_SPACE);
+ fp = fdopen(sock, "w+");
+ if (fp == NULL)
+ return got_error_from_errno("fdopen");
- err = got_poll_write_full(sock, buf, ret);
- if (err)
- return err;
+ ret = fprintf(fp, "login%s%s\n", hostname != NULL ? " " : "",
+ hostname != NULL ? hostname : "");
+ if (ret < 0) {
+ err = got_error_from_errno("fprintf");
+ goto done;
+ }
/*
* gotwebd will return "ok URL", likewise terminated by \n,
* in chunks until we have read all of it.
* For forward compatibilty, ignore any trailing lines received.
*/
- url = calloc(1, sizeof(buf));
- if (url == NULL)
- return got_error_from_errno("calloc");
+ linelen = getline(&line, &linesize, fp);
+ if (linelen == -1) {
+ err = got_error(GOT_ERR_EOF);
+ if (ferror(fp))
+ err = got_error_from_errno("getline");
+ goto done;
+ }
- size = sizeof(buf);
- remain = size;
-
- memset(buf, 0, sizeof(buf)); /* reusing buf with strlcat below */
-
- for (;;) {
- size_t len;
- char *eol;
-
- err = got_poll_read_full(sock, &len, buf, sizeof(buf) - 1, 1);
- if (err)
- goto done;
-
- if (len == 0) {
- err = got_error(GOT_ERR_EOF);
- goto done;
- } else if (len >= remain) { /* should not happen */
- err = got_error(GOT_ERR_NO_SPACE);
- goto done;
- }
-
- buf[len] = '\0';
+ if (strncmp(line, "ok ", 3) == 0) {
+ fprintf(out, "Login successful. Please visit the following "
+ "URL within the next %d minutes: %s\n",
+ GOTWEBD_AUTH_TIMEOUT / 60, line + 3);
+ goto done;
+ }
- eol = memchr(buf, '\n', len);
- if (eol)
- *eol = '\0';
-
- if (strlcat(url, buf, size) >= size) {
- err = got_error(GOT_ERR_NO_SPACE);
- goto done;
- }
-
- if (eol)
- break;
-
- remain -= len;
- if (remain < sizeof(buf)) {
- size_t newsize = size + sizeof(buf);
- char *p;
-
- p = realloc(url, newsize);
- if (p == NULL) {
- err = got_error_from_errno("realloc");
- goto done;
- }
- url = p;
- size = newsize;
- remain += sizeof(buf);
- }
+ if (strncmp(line, "err ", 4) == 0) {
+ err = got_error_fmt(GOT_ERR_AUTH_FAILED, "%s", line + 4);
+ goto done;
}
- if (strncmp(url, "ok ", 3) == 0) {
- if (asprintf(&greeting, "Login successful. Please visit the "
- "following URL within the next %d minutes: ",
- GOTWEBD_AUTH_TIMEOUT / 60) == -1) {
- err = got_error_from_errno("asprintf");
- goto done;
- }
- err = got_poll_write_full(outfd, greeting, strlen(greeting));
- if (err)
- goto done;
- err = got_poll_write_full(outfd, url + 3, strlen(url) - 3);
- } else
- err = got_poll_write_full(outfd, url, strlen(url));
+ err = got_error(GOT_ERR_UNKNOWN_COMMAND);
done:
- if (err && err->code != GOT_ERR_EOF) {
- const struct got_error *err2;
-
- err2 = got_error_fmt(err->code, "%s", getprogname());
- got_poll_write_full(outfd, err2->msg, strlen(err2->msg));
- }
- free(url);
- free(greeting);
+ if (line != NULL)
+ free(line);
+ if (fp != NULL && fclose(fp) == EOF && err == NULL)
+ err = got_error_from_errno("fclose");
return err;
}
if (pledge("stdio", NULL) == -1)
err(1, "pledge");
#endif
- error = weblogin(STDOUT_FILENO, sock, hostname);
+ error = weblogin(stdout, sock, hostname);
} else {
#ifndef PROFILE
if (pledge("stdio recvfd", NULL) == -1)
blob - 870e76a6fec7cb1fd96cdd2f47457c6ab86988d8
blob + 5f07c0e62e56e9d031e63207e86c09c7d8370d3e
--- include/got_error.h
+++ include/got_error.h
#define GOT_ERR_GROUP_EXISTS 179
#define GOT_ERR_AUTHORIZED_KEY 180
#define GOT_ERR_CONNECTION_LIMIT 190
+#define GOT_ERR_AUTH_FAILED 191
+#define GOT_ERR_UNKNOWN_COMMAND 192
struct got_error {
int code;
blob - 922cdad6e22538c24d67ad78bf152e9edef33f49
blob + d08ece89944ab437a2407f75eb9b3513f6b34eaa
--- lib/error.c
+++ lib/error.c
{ GOT_ERR_GROUP_EXISTS, "group already exists" },
{ GOT_ERR_AUTHORIZED_KEY, "no authorized key found" },
{ GOT_ERR_CONNECTION_LIMIT, "connection limit exceeded" },
+ { GOT_ERR_AUTH_FAILED, "authentication failed" },
+ { GOT_ERR_UNKNOWN_COMMAND, "unknown command" },
};
static struct got_custom_error {