📄 security-util.c
字号:
if (*size > 128*NETWORK_BLOCK_BYTES || *size < 0) { if (isprint((int)(*size ) & 0xFF) && isprint((int)(*size >> 8 ) & 0xFF) && isprint((int)(*size >> 16) & 0xFF) && isprint((int)(*size >> 24) & 0xFF) && isprint((*handle ) & 0xFF) && isprint((*handle >> 8 ) & 0xFF) && isprint((*handle >> 16) & 0xFF) && isprint((*handle >> 24) & 0xFF)) { char s[101]; int i; s[0] = ((int)(*size) >> 24) & 0xFF; s[1] = ((int)(*size) >> 16) & 0xFF; s[2] = ((int)(*size) >> 8) & 0xFF; s[3] = ((int)(*size) ) & 0xFF; s[4] = (*handle >> 24) & 0xFF; s[5] = (*handle >> 16) & 0xFF; s[6] = (*handle >> 8 ) & 0xFF; s[7] = (*handle ) & 0xFF; i = 8; s[i] = ' '; while(i<100 && isprint((int)s[i]) && s[i] != '\n') { switch(net_read(fd, &s[i], 1, 0)) { case -1: s[i] = '\0'; break; case 0: s[i] = '\0'; break; default: dbprintf(_("read: %c\n"), s[i]); i++; s[i]=' '; break; } } s[i] = '\0'; *errmsg = newvstrallocf(*errmsg, _("tcpm_recv_token: invalid size: %s"), s); dbprintf(_("tcpm_recv_token: invalid size %s\n"), s); } else { *errmsg = newvstrallocf(*errmsg, _("tcpm_recv_token: invalid size")); dbprintf(_("tcpm_recv_token: invalid size %zd\n"), *size); } *size = -1; return -1; } amfree(*buf); *buf = alloc((size_t)*size); if(*size == 0) { auth_debug(1, _("tcpm_recv_token: read EOF from %d\n"), *handle); *errmsg = newvstrallocf(*errmsg, _("EOF")); return 0; } switch (net_read(fd, *buf, (size_t)*size, timeout)) { case -1: if (errmsg) *errmsg = newvstrallocf(*errmsg, _("recv error: %s"), strerror(errno)); auth_debug(1, _("tcpm_recv_token: B return(-1)\n")); return (-1); case 0: *size = 0; *errmsg = newvstrallocf(*errmsg, _("SOCKET_EOF")); auth_debug(1, _("tcpm_recv_token: B return(0)\n")); return (0); default: break; } auth_debug(1, _("tcpm_recv_token: read %zd bytes from %d\n"), *size, *handle); if (*size > 0 && rc->driver->data_decrypt != NULL) { void *decbuf; ssize_t decsize; rc->driver->data_decrypt(rc, *buf, *size, &decbuf, &decsize); if (*buf != (char *)decbuf) { amfree(*buf); *buf = (char *)decbuf; } *size = decsize; } return((*size));}voidtcpm_close_connection( void *h, char *hostname){ struct sec_handle *rh = h; (void)hostname; if (rh && rh->rc && rh->rc->toclose == 0) { rh->rc->toclose = 1; sec_tcp_conn_put(rh->rc); }}/* * Accept an incoming connection on a stream_server socket * Nothing needed for tcpma. */inttcpma_stream_accept( void * s){ (void)s; /* Quiet unused parameter warning */ return (0);}/* * Return a connected stream. For sec, this means setup a stream * with the supplied handle. */void *tcpma_stream_client( void * h, int id){ struct sec_handle *rh = h; struct sec_stream *rs; assert(rh != NULL); if (id <= 0) { security_seterror(&rh->sech, _("%d: invalid security stream id"), id); return (NULL); } rs = alloc(SIZEOF(*rs)); security_streaminit(&rs->secstr, rh->sech.driver); rs->handle = id; rs->ev_read = NULL; rs->closed_by_me = 0; rs->closed_by_network = 0; if (rh->rc) { rs->rc = rh->rc; rh->rc->refcnt++; } else { rs->rc = sec_tcp_conn_get(rh->hostname, 0); rs->rc->driver = rh->sech.driver; rh->rc = rs->rc; } auth_debug(1, _("sec: stream_client: connected to stream %d\n"), id); return (rs);}/* * Create the server end of a stream. For sec, this means setup a stream * object and allocate a new handle for it. */void *tcpma_stream_server( void * h){ struct sec_handle *rh = h; struct sec_stream *rs; assert(rh != NULL); rs = alloc(SIZEOF(*rs)); security_streaminit(&rs->secstr, rh->sech.driver); rs->closed_by_me = 0; rs->closed_by_network = 0; if (rh->rc) { rs->rc = rh->rc; rs->rc->refcnt++; } else { rs->rc = sec_tcp_conn_get(rh->hostname, 0); rs->rc->driver = rh->sech.driver; rh->rc = rs->rc; } /* * Stream should already be setup! */ if (rs->rc->read < 0) { sec_tcp_conn_put(rs->rc); amfree(rs); security_seterror(&rh->sech, _("lost connection to %s"), rh->hostname); return (NULL); } assert(strcmp(rh->hostname, rs->rc->hostname) == 0); /* * so as not to conflict with the amanda server's handle numbers, * we start at 500000 and work down */ rs->handle = 500000 - newhandle++; rs->ev_read = NULL; auth_debug(1, _("sec: stream_server: created stream %d\n"), rs->handle); return (rs);}/* * Close and unallocate resources for a stream. */voidtcpma_stream_close( void * s){ struct sec_stream *rs = s; char buf = 0; assert(rs != NULL); auth_debug(1, _("sec: tcpma_stream_close: closing stream %d\n"), rs->handle); if(rs->closed_by_network == 0 && rs->rc->write != -1) tcpm_stream_write(rs, &buf, 0); security_stream_read_cancel(&rs->secstr); if(rs->closed_by_network == 0) sec_tcp_conn_put(rs->rc); amfree(rs);}/* * Create the server end of a stream. For bsdudp, this means setup a tcp * socket for receiving a connection. */void *tcp1_stream_server( void * h){ struct sec_stream *rs = NULL; struct sec_handle *rh = h; assert(rh != NULL); rs = alloc(SIZEOF(*rs)); security_streaminit(&rs->secstr, rh->sech.driver); rs->closed_by_me = 0; rs->closed_by_network = 0; if (rh->rc) { rs->rc = rh->rc; rs->handle = 500000 - newhandle++; rs->rc->refcnt++; rs->socket = 0; /* the socket is already opened */ } else { rh->rc = sec_tcp_conn_get(rh->hostname, 1); rh->rc->driver = rh->sech.driver; rs->rc = rh->rc; rs->socket = stream_server(rh->udp->peer.ss_family, &rs->port, STREAM_BUFSIZE, STREAM_BUFSIZE, 0); if (rs->socket < 0) { security_seterror(&rh->sech, _("can't create server stream: %s"), strerror(errno)); amfree(rs); return (NULL); } rh->rc->read = rs->socket; rh->rc->write = rs->socket; rs->handle = (int)rs->port; } rs->fd = -1; rs->ev_read = NULL; return (rs);}/* * Accepts a new connection on unconnected streams. Assumes it is ok to * block on accept() */inttcp1_stream_accept( void * s){ struct sec_stream *bs = s; assert(bs != NULL); assert(bs->socket != -1); assert(bs->fd < 0); if (bs->socket > 0) { bs->fd = stream_accept(bs->socket, 30, STREAM_BUFSIZE, STREAM_BUFSIZE); if (bs->fd < 0) { security_stream_seterror(&bs->secstr, _("can't accept new stream connection: %s"), strerror(errno)); return (-1); } bs->rc->read = bs->fd; bs->rc->write = bs->fd; } return (0);}/* * Return a connected stream */void *tcp1_stream_client( void * h, int id){ struct sec_stream *rs = NULL; struct sec_handle *rh = h; assert(rh != NULL); rs = alloc(SIZEOF(*rs)); security_streaminit(&rs->secstr, rh->sech.driver); rs->handle = id; rs->ev_read = NULL; rs->closed_by_me = 0; rs->closed_by_network = 0; if (rh->rc) { rs->rc = rh->rc; rh->rc->refcnt++; } else { rh->rc = sec_tcp_conn_get(rh->hostname, 1); rh->rc->driver = rh->sech.driver; rs->rc = rh->rc; rh->rc->read = stream_client(rh->hostname, (in_port_t)id, STREAM_BUFSIZE, STREAM_BUFSIZE, &rs->port, 0); if (rh->rc->read < 0) { security_seterror(&rh->sech, _("can't connect stream to %s port %d: %s"), rh->hostname, id, strerror(errno)); amfree(rs); return (NULL); } rh->rc->write = rh->rc->read; } rs->socket = -1; /* we're a client */ rh->rs = rs; return (rs);}inttcp_stream_write( void * s, const void *buf, size_t size){ struct sec_stream *rs = s; assert(rs != NULL); if (fullwrite(rs->fd, buf, size) < 0) { security_stream_seterror(&rs->secstr, _("write error on stream %d: %s"), rs->port, strerror(errno)); return (-1); } return (0);}char *bsd_prefix_packet( void * h, pkt_t * pkt){ struct sec_handle *rh = h; struct passwd *pwd; char *buf; if (pkt->type != P_REQ) return ""; if ((pwd = getpwuid(getuid())) == NULL) { security_seterror(&rh->sech, _("can't get login name for my uid %ld"), (long)getuid()); return(NULL); } buf = alloc(16+strlen(pwd->pw_name)); strncpy(buf, "SECURITY USER ", (16 + strlen(pwd->pw_name))); strncpy(&buf[14], pwd->pw_name, (16 + strlen(pwd->pw_name) - 14)); buf[14 + strlen(pwd->pw_name)] = '\n'; buf[15 + strlen(pwd->pw_name)] = '\0'; return (buf);}/* * Check the security of a received packet. Returns negative on security * violation, or returns 0 if ok. Removes the security info from the pkt_t. */intbsd_recv_security_ok( struct sec_handle * rh, pkt_t * pkt){ char *tok, *security, *body, *result; char *service = NULL, *serviceX, *serviceY; char *security_line; char *s, ch; size_t len; in_port_t port; /* * Now, find the SECURITY line in the body, and parse it out * into an argv. */ if (strncmp_const(pkt->body, "SECURITY ") == 0) { security = pkt->body; len = 0; while(*security != '\n' && len < pkt->size) { security++; len++; } if(*security == '\n') { body = security+1; *security = '\0'; security_line = stralloc(pkt->body); security = pkt->body + strlen("SECURITY "); } else { body = pkt->body; security_line = NULL; security = NULL; } } else { body = pkt->body; security_line = NULL; security = NULL; } /* * Now, find the SERVICE line in the body, and parse it out * into an argv. */ s = body; if (strncmp_const_skip(s, "SERVICE ", s, ch) == 0) { serviceX = stralloc(s); serviceY = strtok(serviceX, "\n"); if (serviceY) service = stralloc(serviceY); amfree(serviceX); } /* * We need to do different things depending on which type of packet * this is. */ switch (pkt->type) { case P_REQ: /* * Request packets must come from a reserved port */ port = SS_GET_PORT(&rh->peer); if (port >= IPPORT_RESERVED) { security_seterror(&rh->sech, _("host %s: port %u not secure"), rh->hostname, (unsigned int)port); amfree(service); amfree(security_line); return (-1); } if (!service) { security_seterror(&rh->sech, _("packet as no SERVICE line")); amfree(security_line); return (-1); } /* * Request packets contain a remote username. We need to check * that we allow it in. * * They will look like: * SECURITY USER [username] */ /* there must be some security info */ if (security == NULL) { security_seterror(&rh->sech, _("no bsd SECURITY for P_REQ")); amfree(service); return (-1); } /* second word must be USER */ if ((tok = strtok(security, " ")) == NULL) { security_seterror(&rh->sech, _("SECURITY line: %s"), security_line); amfree(service); amfree(security_line); return (-1); /* default errmsg */ } if (strcmp(tok, "USER") != 0) { security_seterror(&rh->sech, _("REQ SECURITY line parse error, expecting USER, got %s"), tok); amfree(service); amfree(security_line); return (-1); } /* the third word is the username */ if ((tok = strtok(NULL, "")) == NULL) { security_seterror(&rh->sech, _("SECURITY line: %s"), security_line); amfree(security_line); return (-1); /* default errmsg */ } if ((result = check_user(rh, tok, service)) != NULL) { security_seterror(&rh->sech, "%s", result); amfree(service); amfree(result); amfree(security_line); return (-1); } /* we're good to go */ break; default: break; } amfree(service); amfree(security_line); /* * If there is security info at the front of the packet, we need to * shift the rest of the data up and nuke it. */ if (body != pkt->body) memmove(pkt->body, body, strlen(body) + 1); return (0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -