/* * This function establishes a connection to the specified ip and port and * sends a command to varnishd. If varnishd returns an OK status, the result * is printed and 0 returned. Else, an error message is printed and 1 is * returned */ static int cli_sock(struct vadmin_config_t *vadmin, struct agent_core_t *core) { int fd; unsigned status; char *answer = NULL; char buf[CLI_AUTH_RESPONSE_LEN + 1]; n_arg_sock(core); if (core->config->T_arg == NULL) { logger(vadmin->logger, "No T-arg (Administration port) available. Varnishadm-commands wont work."); return (-1); } vadmin->sock = VSS_open(vadmin->logger, core->config->T_arg, core->config->timeout); if (vadmin->sock < 0) { logger(vadmin->logger, "Connection failed (%s)", core->config->T_arg); return (-1); } (void)VCLI_ReadResult(vadmin->sock, &status, &answer, core->config->timeout); if (status == CLIS_AUTH) { if (core->config->S_arg == NULL) { logger(vadmin->logger, "Authentication required"); assert(close(vadmin->sock) == 0); return(-1); } fd = open(core->config->S_arg, O_RDONLY); if (fd < 0) { logger(vadmin->logger, "Cannot open \"%s\": %s", core->config->S_arg, strerror(errno)); assert(close(vadmin->sock) == 0); return (-1); } VCLI_AuthResponse(fd, answer, buf); assert(close(fd) == 0); free(answer); cli_write(vadmin->sock, "auth "); cli_write(vadmin->sock, buf); cli_write(vadmin->sock, "\n"); (void)VCLI_ReadResult(vadmin->sock, &status, &answer, core->config->timeout); } if (status != CLIS_OK) { logger(vadmin->logger, "Rejected %u\n%s", status, answer); assert(close(vadmin->sock) == 0); return (-1); } free(answer); cli_write(vadmin->sock, "ping\n"); (void)VCLI_ReadResult(vadmin->sock, &status, &answer, core->config->timeout); if (status != CLIS_OK || strstr(answer, "PONG") == NULL) { logger(vadmin->logger, "No pong received from server"); assert(close(vadmin->sock) == 0); return(-1); } free(answer); vadmin->state = 1; return (vadmin->sock); }
static void vadmin_run(struct vadmin_config_t *vadmin, char *cmd, struct ipc_ret_t *ret) { int sock = vadmin->sock; int nret; assert(cmd); nret = cli_write(sock, cmd); if (!nret) { logger(vadmin->logger, "Communication error with varnishd."); ret->status = 400; ret->answer = strdup("Varnishd disconnected"); vadmin->state = 0; return; } nret = cli_write(sock, "\n"); if (!nret) { logger(vadmin->logger, "Communication error with varnishd."); ret->status = 400; ret->answer = strdup("Varnishd disconnected"); vadmin->state = 0; return; } logger(vadmin->logger, "Running %s",cmd); (void)VCLI_ReadResult(sock, &ret->status, &ret->answer, 2000); logger(vadmin->logger, "Got: %d ",ret->status, ret->answer); }
static void do_args(int sock, int argc, char * const *argv) { int i; unsigned status; char *answer = NULL; for (i=0; i<argc; i++) { /* XXX: We should really CLI-quote these */ if (i > 0) cli_write(sock, " "); cli_write(sock, argv[i]); } cli_write(sock, "\n"); (void)VCLI_ReadResult(sock, &status, &answer, 2000); /* XXX: AZ() ? */ (void)close(sock); printf("%s\n", answer); if (status == CLIS_OK) { exit(0); } fprintf(stderr, "Command failed with error code %u\n", status); exit(1); }
/* * This function establishes a connection to the specified ip and port and * sends a command to varnishd. If varnishd returns an OK status, the result * is printed and 0 returned. Else, an error message is printed and 1 is * returned */ static int cli_sock(const char *T_arg, const char *S_arg) { int fd; int sock; unsigned status; char *answer = NULL; char buf[CLI_AUTH_RESPONSE_LEN + 1]; const char *err; sock = VTCP_open(T_arg, NULL, timeout, &err); if (sock < 0) { fprintf(stderr, "Connection failed (%s): %s\n", T_arg, err); return (-1); } (void)VCLI_ReadResult(sock, &status, &answer, timeout); if (status == CLIS_AUTH) { if (S_arg == NULL) { fprintf(stderr, "Authentication required\n"); AZ(close(sock)); return(-1); } fd = open(S_arg, O_RDONLY); if (fd < 0) { fprintf(stderr, "Cannot open \"%s\": %s\n", S_arg, strerror(errno)); AZ(close(sock)); return (-1); } VCLI_AuthResponse(fd, answer, buf); AZ(close(fd)); free(answer); cli_write(sock, "auth "); cli_write(sock, buf); cli_write(sock, "\n"); (void)VCLI_ReadResult(sock, &status, &answer, timeout); } if (status != CLIS_OK) { fprintf(stderr, "Rejected %u\n%s\n", status, answer); AZ(close(sock)); free(answer); return (-1); } free(answer); cli_write(sock, "ping\n"); (void)VCLI_ReadResult(sock, &status, &answer, timeout); if (status != CLIS_OK || strstr(answer, "PONG") == NULL) { fprintf(stderr, "No pong received from server\n"); AZ(close(sock)); free(answer); return (-1); } free(answer); return (sock); }
void send_line(char *l) { if (l) { cli_write(_line_sock, l); cli_write(_line_sock, "\n"); add_history(l); } else { RL_EXIT(0); } }
static void send_line(char *l) { if (l) { cli_write(_line_sock, l); cli_write(_line_sock, "\n"); add_history(l); rl_callback_handler_install("varnish> ", send_line); } else { RL_EXIT(0); } }
static int /* O - 0 = success, non-0 = failure */ smb_print(struct cli_state *cli, /* I - SMB connection */ char *title, /* I - Title/job name */ FILE *fp) /* I - File to print */ { int fnum; /* File number */ int nbytes, /* Number of bytes read */ tbytes; /* Total bytes read */ char buffer[8192], /* Buffer for copy */ *ptr; /* Pointer into tile */ /* * Sanitize the title... */ for (ptr = title; *ptr; ptr ++) if (!isalnum((int)*ptr) && !isspace((int)*ptr)) *ptr = '_'; /* * Open the printer device... */ if ((fnum = cli_open(cli, title, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE)) == -1) { fprintf(stderr, "ERROR: %s opening remote spool %s\n", cli_errstr(cli), title); return (1); } /* * Copy the file to the printer... */ if (fp != stdin) rewind(fp); tbytes = 0; while ((nbytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) { if (cli_write(cli, fnum, 0, buffer, tbytes, nbytes) != nbytes) { fprintf(stderr, "ERROR: Error writing spool: %s\n", cli_errstr(cli)); break; } tbytes += nbytes; } if (!cli_close(cli, fnum)) { fprintf(stderr, "ERROR: %s closing remote spool %s\n", cli_errstr(cli), title); return (1); } else return (0); }
/***************************************************** a wrapper for pwrite() *******************************************************/ ssize_t smbw_pwrite(int fd, void *buf, size_t count, off_t ofs) { struct smbw_file *file; int ret; smbw_busy++; file = smbw_file(fd); if (!file) { errno = EBADF; smbw_busy--; return -1; } ret = cli_write(&file->srv->cli, file->f->cli_fd, 0, buf, ofs, count); if (ret == -1) { errno = smbw_errno(&file->srv->cli); smbw_busy--; return -1; } smbw_busy--; return ret; }
/* * No arguments given, simply pass bytes on stdin/stdout and CLI socket */ static void pass(int sock) { struct pollfd fds[2]; char buf[1024]; int i; char *answer = NULL; unsigned u, status; ssize_t n; fds[0].fd = sock; fds[0].events = POLLIN; fds[1].fd = 0; fds[1].events = POLLIN; while (1) { i = poll(fds, 2, -1); if (i == -1 && errno == EINTR) { continue; } assert(i > 0); if (fds[0].revents & POLLIN) { u = VCLI_ReadResult(fds[0].fd, &status, &answer, timeout); if (u) { if (status == CLIS_COMMS) RL_EXIT(0); if (answer) fprintf(stderr, "%s\n", answer); RL_EXIT(1); } sprintf(buf, "%u\n", status); u = write(1, buf, strlen(buf)); if (answer) { u = write(1, answer, strlen(answer)); u = write(1, "\n", 1); free(answer); answer = NULL; } } if (fds[1].revents & POLLIN || fds[1].revents & POLLHUP) { n = read(fds[1].fd, buf, sizeof buf - 1); if (n == 0) { AZ(shutdown(sock, SHUT_WR)); fds[1].fd = -1; } else if (n < 0) { RL_EXIT(0); } else { buf[n] = '\0'; cli_write(sock, buf); } } } }
void nb_writex(int handle, int offset, int size, int ret_size) { int i; if (buf[0] == 0) memset(buf, 1, sizeof(buf)); i = find_handle(handle); if (cli_write(c, ftable[i].fd, 0, buf, offset, size) != ret_size) { printf("(%d) ERROR: write failed on handle %d, fd %d \ errno %d (%s)\n", line_count, handle, ftable[i].fd, errno, strerror(errno)); exit(1); }
static void vadmin_run(struct vadmin_config_t *vadmin, char *cmd, struct ipc_ret_t *ret) { int sock = vadmin->sock; char *p; int nret; assert(cmd); for (p = cmd; *p; p++) { if (!isspace(*p)) break; } if (*p == '\0') { /* cmd is all whitespace */ ret->answer = strdup(""); return; } nret = cli_write(sock, cmd); if (!nret) { warnlog(vadmin->logger, "Communication error with varnishd."); ret->status = 400; ret->answer = strdup("Varnishd disconnected"); vadmin->state = 0; return; } nret = cli_write(sock, "\n"); if (!nret) { warnlog(vadmin->logger, "Communication error with varnishd."); ret->status = 400; ret->answer = strdup("Varnishd disconnected"); vadmin->state = 0; return; } debuglog(vadmin->logger, "Running '%s'",cmd); (void)VCLI_ReadResult(sock, &ret->status, &ret->answer, 2000); debuglog(vadmin->logger, "Got: %d ",ret->status); }
END_TEST START_TEST(test_cli) { int ostdout, spair[2]; struct parent_msg msg = {}; char buf[2048]; int sobuf = 2048; ostdout = dup(STDOUT_FILENO); fail_if(ostdout == -1, "dup failed: %s", strerror(errno)); fail_if(socketpair(AF_UNIX, SOCK_STREAM, 0, spair) == -1, "socketpair creation failed: %s", strerror(errno)); setsockopt(spair[0], SOL_SOCKET, SO_SNDBUF, &sobuf, sizeof(sobuf)); setsockopt(spair[1], SOL_SOCKET, SO_RCVBUF, &sobuf, sizeof(sobuf)); dup2(spair[0], STDOUT_FILENO); mark_point(); cli_header(); fflush(stdout); fail_if(read(spair[1], buf, sizeof(buf)) < 0, "read failed"); fail_if(strstr(buf, "Capability Codes:") != buf, "invalid cli_header output"); fail_if(strstr(buf, "Device ID") == NULL, "invalid cli_header output"); mark_point(); strlcpy(msg.name, "eth0", IFNAMSIZ); msg.proto = PROTO_CDP; msg.peer[PEER_HOSTNAME] = strdup("router.local"); msg.peer[PEER_PORTNAME] = strdup("TenGigabitEthernet42/64"); cli_write(&msg, 42); fflush(stdout); fail_if(read(spair[1], buf, sizeof(buf)) < 0, "read failed"); fail_if(strstr(buf, "router") != buf, "invalid cli_write output"); fail_if(strstr(buf, "Te42/64") == NULL, "invalid cli_write output"); close(spair[0]); close(spair[1]); dup2(ostdout, STDOUT_FILENO); close(ostdout); peer_free(msg.peer); }
static BOOL rpc_send_auth_reply(struct cli_state *cli, prs_struct *rdata, uint32 rpc_call_id) { prs_struct rpc_out; ssize_t ret; prs_init(&rpc_out, RPC_HEADER_LEN + RPC_HDR_AUTHA_LEN, /* need at least this much */ cli->mem_ctx, MARSHALL); if (!NT_STATUS_IS_OK(create_rpc_bind_resp(cli, rpc_call_id, &rpc_out))) { return False; } if ((ret = cli_write(cli, cli->nt_pipe_fnum, 0x8, prs_data_p(&rpc_out), 0, (size_t)prs_offset(&rpc_out))) != (ssize_t)prs_offset(&rpc_out)) { DEBUG(0,("rpc_send_auth_reply: cli_write failed. Return was %d\n", (int)ret)); prs_mem_free(&rpc_out); return False; } prs_mem_free(&rpc_out); return True; }
/* * No arguments given, simply pass bytes on stdin/stdout and CLI socket * Send a "banner" to varnish, to provoke a welcome message. */ static void interactive(int sock) { struct pollfd fds[2]; char buf[1024]; int i; char *answer = NULL; unsigned u, status; _line_sock = sock; rl_already_prompted = 1; rl_callback_handler_install("varnish> ", send_line); rl_attempted_completion_function = varnishadm_completion; fds[0].fd = sock; fds[0].events = POLLIN; fds[1].fd = 0; fds[1].events = POLLIN; /* Grab the commands, for completion */ cli_write(sock, "help\n"); u = VCLI_ReadResult(fds[0].fd, &status, &answer, timeout); if (!u) { char *t, c[128]; if (status == CLIS_COMMS) { RL_EXIT(0); } t = answer; i = 0; while (*t) { if (sscanf(t, "%127s", c) == 1) { commands[i++] = strdup(c); while (*t != '\n' && *t != '\0') t++; if (*t == '\n') t++; } else { /* what? */ fprintf(stderr, "Unknown command '%s' parsing " "help output. Tab completion may be " "broken\n", t); break; } } } cli_write(sock, "banner\n"); while (1) { i = poll(fds, 2, -1); if (i == -1 && errno == EINTR) { continue; } assert(i > 0); if (fds[0].revents & POLLIN) { /* Get rid of the prompt, kinda hackish */ u = write(1, "\r \r", 13); u = VCLI_ReadResult(fds[0].fd, &status, &answer, timeout); if (u) { if (status == CLIS_COMMS) RL_EXIT(0); if (answer) fprintf(stderr, "%s\n", answer); RL_EXIT(1); } sprintf(buf, "%u\n", status); u = write(1, buf, strlen(buf)); if (answer) { u = write(1, answer, strlen(answer)); u = write(1, "\n", 1); free(answer); answer = NULL; } rl_forced_update_display(); } if (fds[1].revents & POLLIN) { rl_callback_read_char(); } } }
ssize_t SMBC_write_ctx(SMBCCTX *context, SMBCFILE *file, const void *buf, size_t count) { int ret; off_t offset; char *server = NULL, *share = NULL, *user = NULL, *password = NULL; char *path = NULL; char *targetpath = NULL; struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); /* First check all pointers before dereferencing them */ if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } if (!file || !SMBC_dlist_contains(context->internal->files, file)) { errno = EBADF; TALLOC_FREE(frame); return -1; } /* Check that the buffer exists ... */ if (buf == NULL) { errno = EINVAL; TALLOC_FREE(frame); return -1; } offset = file->offset; /* See "offset" comment in SMBC_read_ctx() */ /*d_printf(">>>write: parsing %s\n", file->fname);*/ if (SMBC_parse_path(frame, context, file->fname, NULL, &server, &share, &path, &user, &password, NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } /*d_printf(">>>write: resolving %s\n", path);*/ if (!cli_resolve_path(frame, "", file->srv->cli, path, &targetcli, &targetpath)) { d_printf("Could not resolve %s\n", path); errno = ENOENT; TALLOC_FREE(frame); return -1; } /*d_printf(">>>write: resolved path as %s\n", targetpath);*/ ret = cli_write(targetcli, file->cli_fd, 0, (char *)buf, offset, count); if (ret <= 0) { errno = SMBC_errno(context, targetcli); TALLOC_FREE(frame); return -1; } file->offset += ret; TALLOC_FREE(frame); return ret; /* Success, 0 bytes of data ... */ }
BOOL rpc_api_pipe_req(struct cli_state *cli, uint8 op_num, prs_struct *data, prs_struct *rdata) { uint32 auth_len, real_auth_len, auth_hdr_len, max_data, data_left, data_sent; NTSTATUS nt_status; BOOL ret = False; uint32 callid = 0; fstring dump_name; auth_len = 0; real_auth_len = 0; auth_hdr_len = 0; if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) { if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) { auth_len = RPC_AUTH_NTLMSSP_CHK_LEN; } if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) { auth_len = RPC_AUTH_NETSEC_CHK_LEN; } auth_hdr_len = RPC_HDR_AUTH_LEN; } /* * calc how much actual data we can send in a PDU fragment */ max_data = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN - auth_hdr_len - auth_len - 8; for (data_left = prs_offset(data), data_sent = 0; data_left > 0;) { prs_struct outgoing_packet; prs_struct sec_blob; uint32 data_len, send_size; uint8 flags = 0; uint32 auth_padding = 0; DATA_BLOB sign_blob; /* * how much will we send this time */ send_size = MIN(data_left, max_data); if (!prs_init(&sec_blob, send_size, /* will need at least this much */ cli->mem_ctx, MARSHALL)) { DEBUG(0,("Could not malloc %u bytes", send_size+auth_padding)); return False; } if(!prs_append_some_prs_data(&sec_blob, data, data_sent, send_size)) { DEBUG(0,("Failed to append data to netsec blob\n")); prs_mem_free(&sec_blob); return False; } /* * NT expects the data that is sealed to be 8-byte * aligned. The padding must be encrypted as well and * taken into account when generating the * authentication verifier. The amount of padding must * be stored in the auth header. */ if (cli->pipe_auth_flags) { size_t data_and_padding_size; int auth_type; int auth_level; prs_align_uint64(&sec_blob); get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level); data_and_padding_size = prs_offset(&sec_blob); auth_padding = data_and_padding_size - send_size; /* insert the auth header */ if(!create_auth_hdr(&sec_blob, auth_type, auth_level, auth_padding)) { prs_mem_free(&sec_blob); return False; } /* create an NTLMSSP signature */ if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) { /* * Seal the outgoing data if requested. */ if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) { nt_status = ntlmssp_seal_packet(cli->ntlmssp_pipe_state, (unsigned char*)prs_data_p(&sec_blob), data_and_padding_size, &sign_blob); if (!NT_STATUS_IS_OK(nt_status)) { prs_mem_free(&sec_blob); return False; } } else if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) { nt_status = ntlmssp_sign_packet(cli->ntlmssp_pipe_state, (unsigned char*)prs_data_p(&sec_blob), data_and_padding_size, &sign_blob); if (!NT_STATUS_IS_OK(nt_status)) { prs_mem_free(&sec_blob); return False; } } /* write auth footer onto the packet */ real_auth_len = sign_blob.length; prs_copy_data_in(&sec_blob, (char *)sign_blob.data, sign_blob.length); data_blob_free(&sign_blob); } else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) { size_t parse_offset_marker; RPC_AUTH_NETSEC_CHK verf; DEBUG(10,("SCHANNEL seq_num=%d\n", cli->auth_info.seq_num)); netsec_encode(&cli->auth_info, cli->pipe_auth_flags, SENDER_IS_INITIATOR, &verf, prs_data_p(&sec_blob), data_and_padding_size); cli->auth_info.seq_num++; /* write auth footer onto the packet */ parse_offset_marker = prs_offset(&sec_blob); if (!smb_io_rpc_auth_netsec_chk("", &verf, &sec_blob, 0)) { prs_mem_free(&sec_blob); return False; } real_auth_len = prs_offset(&sec_blob) - parse_offset_marker; } } data_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + prs_offset(&sec_blob); /* * Malloc parse struct to hold it (and enough for alignments). */ if(!prs_init(&outgoing_packet, data_len + 8, cli->mem_ctx, MARSHALL)) { DEBUG(0,("rpc_api_pipe_req: Failed to malloc %u bytes.\n", (unsigned int)data_len )); return False; } if (data_left == prs_offset(data)) flags |= RPC_FLG_FIRST; if (data_left <= max_data) flags |= RPC_FLG_LAST; /* * Write out the RPC header and the request header. */ if(!(callid = create_rpc_request(&outgoing_packet, op_num, data_len, real_auth_len, flags, callid, data_left))) { DEBUG(0,("rpc_api_pipe_req: Failed to create RPC request.\n")); prs_mem_free(&outgoing_packet); prs_mem_free(&sec_blob); return False; } prs_append_prs_data(&outgoing_packet, &sec_blob); prs_mem_free(&sec_blob); DEBUG(100,("data_len: %x data_calc_len: %x\n", data_len, prs_offset(&outgoing_packet))); if (flags & RPC_FLG_LAST) ret = rpc_api_pipe(cli, &outgoing_packet, rdata, RPC_RESPONSE); else { cli_write(cli, cli->nt_pipe_fnum, 0x0008, prs_data_p(&outgoing_packet), data_sent, data_len); } prs_mem_free(&outgoing_packet); data_sent += send_size; data_left -= send_size; } /* Also capture received data */ slprintf(dump_name, sizeof(dump_name) - 1, "reply_%s", cli_pipe_get_name(cli)); prs_dump(dump_name, op_num, rdata); return ret; }
/* * No arguments given, simply pass bytes on stdin/stdout and CLI socket * Send a "banner" to varnish, to provoke a welcome message. */ static void pass(int sock) { struct pollfd fds[2]; char buf[1024]; int i; char *answer = NULL; unsigned u, status; #ifndef HAVE_LIBEDIT int n; #endif #ifdef HAVE_LIBEDIT _line_sock = sock; rl_already_prompted = 1; if (isatty(0)) { rl_callback_handler_install("varnish> ", send_line); } else { rl_callback_handler_install("", send_line); } #endif cli_write(sock, "banner\n"); fds[0].fd = sock; fds[0].events = POLLIN; fds[1].fd = 0; fds[1].events = POLLIN; while (1) { i = poll(fds, 2, -1); assert(i > 0); if (fds[0].revents & POLLIN) { /* Get rid of the prompt, kinda hackish */ u = write(1, "\r \r", 13); u = VCLI_ReadResult(fds[0].fd, &status, &answer, timeout); if (u) { if (status == CLIS_COMMS) RL_EXIT(0); if (answer) fprintf(stderr, "%s\n", answer); RL_EXIT(1); } sprintf(buf, "%u\n", status); u = write(1, buf, strlen(buf)); if (answer) { u = write(1, answer, strlen(answer)); u = write(1, "\n", 1); free(answer); answer = NULL; } #ifdef HAVE_LIBEDIT rl_forced_update_display(); #endif } if (fds[1].revents & POLLIN) { #ifdef HAVE_LIBEDIT rl_callback_read_char(); #else n = read(fds[1].fd, buf, sizeof buf); if (n == 0) { AZ(shutdown(sock, SHUT_WR)); fds[1].fd = -1; } else if (n < 0) { RL_EXIT(0); } else { buf[n] = '\0'; cli_write(sock, buf); } #endif } } }