📄 smb.c
字号:
#include "links.h"#ifndef DISABLE_SMB#define SMBCLIENT 0#define SMBC 1#define N_CLIENTS 2int smb_client = 0;struct smb_connection_info { int client; int list; int cl; int ntext; unsigned char text[1];};void smb_got_data(struct connection *);void smb_got_text(struct connection *);void end_smb_connection(struct connection *);int smbc_get_num(unsigned char *, int *, off_t *);void smb_read_text(struct connection *, int);void smb_func(struct connection *c){ int i; int po[2]; int pe[2]; unsigned char *host, *user, *pass, *port, *data1, *data, *share, *dir; int datal; unsigned char *p; pid_t r; struct smb_connection_info *si; si = mem_alloc(sizeof(struct smb_connection_info) + 2); memset(si, 0, sizeof(struct smb_connection_info)); c->info = si; si->client = smb_client; host = get_host_name(c->url); if (!host) { setcstate(c, S_INTERNAL); abort_connection(c); return; } if (!(user = get_user_name(c->url))) user = stracpy(""); if (!(pass = get_pass(c->url))) pass = stracpy(""); if (!(port = get_port_str(c->url))) port = stracpy(""); if (!(data1 = get_url_data(c->url))) data1 = ""; data = init_str(), datal = 0; add_conv_str(&data, &datal, data1, strlen(data1), -2); for (i = 0; data[i]; i++) if (data[i] < 32 || data[i] == ';' || (data[i] == '"' && smb_client == SMBCLIENT)) {/* ';' shouldn't cause security problems but samba doesn't like it *//* '"' is allowed for smbc */ mem_free(host); mem_free(port); mem_free(user); mem_free(pass); mem_free(data); setcstate(c, S_BAD_URL); abort_connection(c); return; } if ((p = strchr(data, '/'))) share = memacpy(data, p - data), dir = p + 1; else if (*data) { if (!c->cache && get_cache_entry(c->url, &c->cache)) { mem_free(host); mem_free(port); mem_free(user); mem_free(pass); mem_free(data); setcstate(c, S_OUT_OF_MEM); abort_connection(c); return; } if (c->cache->redirect) mem_free(c->cache->redirect); c->cache->redirect = stracpy(c->url); c->cache->redirect_get = 1; add_to_strn(&c->cache->redirect, "/"); c->cache->incomplete = 0; mem_free(host); mem_free(port); mem_free(user); mem_free(pass); mem_free(data); setcstate(c, S_OK); abort_connection(c); return; } else share = stracpy(""), dir = ""; if (!*share) si->list = 1; else if (!*dir || dir[strlen(dir) - 1] == '/' || dir[strlen(dir) - 1] == '\\') si->list = 2; if (c_pipe(po)) { mem_free(host); mem_free(port); mem_free(user); mem_free(pass); mem_free(share); mem_free(data); setcstate(c, -errno); abort_connection(c); return; } if (c_pipe(pe)) { mem_free(host); mem_free(port); mem_free(user); mem_free(pass); mem_free(share); mem_free(data); close(po[0]); close(po[1]); setcstate(c, -errno); abort_connection(c); return; } c->from = 0; r = fork(); if (r == -1) { mem_free(host); mem_free(port); mem_free(user); mem_free(pass); mem_free(share); mem_free(data); close(po[0]); close(po[1]); close(pe[0]); close(pe[1]); setcstate(c, -errno); retry_connection(c); return; } if (!r) { int n; unsigned char *v[32]; unsigned char *uphp; close_fork_tty(); close(1); if (si->list) dup2(pe[1], 1); else dup2(po[1], 1); close(2); dup2(pe[1], 2); close(0); open("/dev/null", O_RDONLY); close(po[0]); close(pe[0]); close(po[1]); close(pe[1]); n = 0; switch (si->client) { case SMBCLIENT: v[n++] = "smbclient"; if (!*share) { v[n++] = "-L"; v[n++] = host; } else { unsigned char *s = stracpy("//"); add_to_strn(&s, host); add_to_strn(&s, "/"); add_to_strn(&s, share); v[n++] = s; if (*pass && !*user) { v[n++] = pass; } } v[n++] = "-N"; v[n++] = "-E"; if (*port) { v[n++] = "-p"; v[n++] = port; } if (*user) { v[n++] = "-U"; if (!*pass) { v[n++] = user; } else { unsigned char *s = stracpy(user); add_to_strn(&s, "%"); add_to_strn(&s, pass); v[n++] = s; } } if (*share) { if (!*dir || dir[strlen(dir) - 1] == '/' || dir[strlen(dir) - 1] == '\\') { if (*dir) { v[n++] = "-D"; v[n++] = dir; } v[n++] = "-c"; v[n++] = "ls"; } else { unsigned char *ss; unsigned char *s = stracpy("get \""); add_to_strn(&s, dir); add_to_strn(&s, "\" -"); while ((ss = strchr(s, '/'))) *ss = '\\'; v[n++] = "-c"; v[n++] = s; } } break; case SMBC: v[n++] = "smbc"; uphp = stracpy(""); if (*user) { add_to_strn(&uphp, user); if (*pass) { add_to_strn(&uphp, ":"); add_to_strn(&uphp, pass); } add_to_strn(&uphp, "@"); } add_to_strn(&uphp, host); if (*port) { add_to_strn(&uphp, ":"); add_to_strn(&uphp, port); } if (!*share) { v[n++] = "-L"; v[n++] = uphp; } else { add_to_strn(&uphp, "/"); add_to_strn(&uphp, share); if (!*dir || dir[strlen(dir) - 1] == '/' || dir[strlen(dir) - 1] == '\\') { add_to_strn(&uphp, "/"); add_to_strn(&uphp, dir); v[n++] = uphp; v[n++] = "-c"; v[n++] = "ls"; } else { unsigned char *d = init_str(); int dl = 0; unsigned char *dp = dir; v[n++] = uphp; v[n++] = "-c"; add_to_str(&d, &dl, "pipe cat "); while (*dp) { if (*dp <= ' ' || *dp == '\\' || *dp == '"' || *dp == '\'' || *dp == '*' || *dp == '?') add_chr_to_str(&d, &dl, '\\'); add_chr_to_str(&d, &dl, *dp); dp++; } v[n++] = d; } } break; default: internal("unsuported smb client"); } v[n++] = NULL; execvp(v[0], (char **)(void *)v); fprintf(stderr, "client not found"); fflush(stderr); _exit(1); } c->pid = r; mem_free(host); mem_free(port); mem_free(user); mem_free(pass); mem_free(share); mem_free(data); c->sock1 = po[0]; c->sock2 = pe[0]; close(po[1]); close(pe[1]); set_handlers(po[0], (void (*)(void *))smb_got_data, NULL, NULL, c); set_handlers(pe[0], (void (*)(void *))smb_got_text, NULL, NULL, c); setcstate(c, S_CONN);}int smbc_get_num(unsigned char *text, int *ptr, off_t *res){ off_t num; int dec, dec_order, unit; int was_digit; int i = *ptr; while (text[i] == ' ' || text[i] == '\t') i++; was_digit = 0; num = 0; while (text[i] >= '0' && text[i] <= '9') { num = num * 10 + text[i] - '0'; i++; was_digit = 1; } dec = 0; dec_order = 1; if (text[i] == '.') { i++; while (text[i] >= '0' && text[i] <= '9') { if (dec_order < 1000000) { dec = dec * 10 + text[i] - '0'; dec_order *= 10; } i++; was_digit = 1; } } if (!was_digit) return -1; if (upcase(text[i]) == 'B') unit = 1; else if (upcase(text[i]) == 'K') unit = 1 << 10; else if (upcase(text[i]) == 'M') unit = 1 << 20; else if (upcase(text[i]) == 'G') unit = 1 << 30; else return -1; i++; *ptr = i; *res = num * unit + (double)dec * ((double)unit / (double)dec_order); return 0;}void smb_read_text(struct connection *c, int sock){ int r; struct smb_connection_info *si = c->info; if ((unsigned)sizeof(struct smb_connection_info) + si->ntext + page_size + 2 > MAXINT) overalloc(); si = mem_realloc(si, sizeof(struct smb_connection_info) + si->ntext + page_size + 2); c->info = si; r = read(sock, si->text + si->ntext, page_size); if (r == -1) { setcstate(c, -errno);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -