commit 0d6b67e271d1f497a862858fce73c5a9b430ef11 from: Omar Polo date: Sat May 17 16:12:52 2025 UTC simplify gotsh weblogin commit - f9d09706c26867a700fc666e9809f029520f5848 commit + 0d6b67e271d1f497a862858fce73c5a9b430ef11 blob - 80fc725d32a21c67dbac7e260514e2a352c549cd blob + 8aab8d4e3b63b817ca0ccd4dcfbf8160525c18f5 --- gotsh/gotsh.c +++ gotsh/gotsh.c @@ -72,31 +72,25 @@ apply_unveil(const char *unix_socket_path) /* 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, @@ -105,83 +99,32 @@ weblogin(int outfd, int sock, const char *hostname) * 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; } @@ -344,7 +287,7 @@ main(int argc, char *argv[]) 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 @@ -196,6 +196,8 @@ #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 @@ -247,6 +247,8 @@ static const struct got_error got_errors[] = { { 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 {