/* $Id: sfspath.C,v 1.8 2001/06/28 04:47:23 dm Exp $ */ /* * * Copyright (C) 1999 David Mazieres (dm@uun.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * */ #include "sfsmisc.h" #include "crypt.h" #include "parseopt.h" bool sfs_ascii2hostid (sfs_hash *hid, const char *p) { const u_char *const up = reinterpret_cast (p); if (armor32len (up) != ascii_hostid_len || p[ascii_hostid_len]) return false; if (hid) { str raw = dearmor32 (p, ascii_hostid_len); memcpy (hid->base (), raw, hid->size ()); } return true; } bool sfsgethost_label (const char *&p) { const char *s = p; while ((*s >= 'a' && *s <= 'z') || (*s >= '0' && *s <= '9') || *s == '-') s++; if (s - p == 0 || s - p > 63) return false; p = s; return true; } bool sfsgethost_dotlabel (const char *&p) { const char *s = p; if (*s++ != '.') return false; if (!sfsgethost_label (s)) return false; p = s; return true; } str sfsgethost (const char *&p) { const char *s = p; if (!sfsgethost_label (s) || !sfsgethost_dotlabel (s)) return NULL; while (sfsgethost_dotlabel (s)) ; if (s - p > 255) return NULL; str host (p, s - p); p = s; return host; } bool sfs_parsepath (str path, str *host, sfs_hash *hostid, u_int16_t *portp) { const char *p = path; u_int16_t port = sfs_port; if (isdigit (*p)) { int64_t atno = strtoi64 (path, const_cast (&p), 10); if (p && *p == '@' && atno > 0 && atno < 0x10000) { port = atno; path = substr (path, p + 1 - path.cstr ()); } p = path; } if (portp) *portp = port; if (!sfsgethost (p)) return false; if (host) host->setbuf (path, p - path); return *p++ == ':' && sfs_ascii2hostid (hostid, p); } bool sfs_mkhostid (sfs_hash *id, const sfs_hostinfo &info) { const char *p = info.hostname; if (info.type != SFS_HOSTINFO || !sfsgethost (p) || *p) { bzero (id->base (), id->size ()); return false; } xdrsuio x; if (!xdr_sfs_hostinfo (&x, const_cast (&info)) || !xdr_sfs_hostinfo (&x, const_cast (&info))) { warn << "sfs_mkhostid (" << info.hostname << ", " << hexdump (id->base (), id->size ()) << "): XDR failed!\n"; bzero (id->base (), id->size ()); return false; } sha1_hashv (id->base (), x.iov (), x.iovcnt ()); return true; } str sfs_hostinfo2path (const sfs_hostinfo &info) { sfs_hash hostid; if (!sfs_mkhostid (&hostid, info)) return NULL; return strbuf () << info.hostname << ":" << armor32 (&hostid, sizeof (hostid)); } bool sfs_ckhostid (const sfs_hash *id, const sfs_hostinfo &info) { sfs_hash rid; return sfs_mkhostid (&rid, info) && !memcmp (&rid, id, sizeof (rid)); } bool sfs_ckpath (str sname, const sfs_hostinfo &info) { str location; sfs_hash hid; return sfs_parsepath (sname, &location, &hid) && location == info.hostname && sfs_ckhostid (&hid, info); } bool sfs_ckci (const sfs_connectinfo &ci, const sfs_hostinfo &info) { if (ci.civers <= 4) return sfs_ckhostid (&ci.ci4->hostid, info); return sfs_ckpath (ci.ci5->sname, info); } bool sfs_checkrevoke (const sfs_pathrevoke &rev) { if (rev.msg.type != SFS_PATHREVOKE || rev.msg.path.type != SFS_HOSTINFO || (rev.msg.redirect && rev.msg.redirect->hostinfo.type != SFS_HOSTINFO)) return false; rabin_pub pk (rev.msg.path.pubkey); if (!pk.verify (xdr2str (rev.msg), rev.sig)) return false; sfs_hash hostid; if (rev.msg.redirect && (!sfs_mkhostid (&hostid, rev.msg.redirect->hostinfo) || implicit_cast (rev.msg.redirect->expire) >= timenow)) return false; return true; }