// -*-c++-*- /* $Id: dbrec2str.C,v 1.2 2002/01/06 19:30:36 dm Exp $ */ /* * * Copyright (C) 2001 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 * */ /* * Converts users to/from the following text representation: * USER:name:uid:version:gid:owner:pubkey:privs:srpinfo:privkey:audit * * Converts groups to/from the following: * GROUP:name:gid:version:owners:members:audit */ #include "authdb.h" #include "wmstr.h" #include "serial.h" #include "rxx.h" #include "parseopt.h" #define AUTHNAME "[A-Za-z][\\w/]{0,31}" #define BADCHAR "\\x00-\\x1f\\x7f-\\xff:" static rxx namerx (AUTHNAME); static rxx colon (":"); static rxx commaplus (",+"); static rxx srprx ("SRP,N=(0x[\\da-f]+),g=(0x[\\da-f]+)," "s=(\\d+\\$[A-Za-z0-9+/]+={0,2}\\$[\\w\\.\\-]*)," "v=(0x[\\da-f]+)"); static rxx nobadrx ("[^"BADCHAR"]*"); static rxx badcharrx ("["BADCHAR"]"); static rxx hexrx ("0x[\\da-fA-F]+"); static rxx decrx ("\\d+"); static bool printname (strbuf &sb, sfs_idname name) { if (!namerx.match (name)) return false; sb << name; return true; } static bool parsename (sfs_idname *name, str s) { if (!namerx.match (s)) return false; *name = s; return true; } #if 0 static bool printnum (strbuf &sb, u_int32_t num) { sb.fmt ("%u", num); return true; } static bool parsenum (u_int32_t *nump, str s) { return convertint (s, nump); } #endif template static bool printlist (strbuf &sb, const rpc_vec &v, bool (*printfn) (strbuf &, T)) { bool first = true; for (const T *tp = v.base (); tp < v.lim (); tp++) { if (first) first = false; else sb << ","; if (!printfn (sb, *tp)) return false; } return true; } template static bool parselist (rpc_vec *vp, str s, bool (*parsefn) (T *, str)) { vec sv; split (&sv, commaplus, s); if (!sv.empty () && !sv.front ().len ()) sv.pop_front (); if (!sv.empty () && !sv.back ().len ()) sv.pop_back (); vp->setsize (sv.size ()); for (size_t i = 0; i < vp->size (); i++) if (!parsefn (&(*vp)[i], sv[i])) return false; return true; } static bool userinfo2str (strbuf &sb, const sfsauth_userinfo *ui) { if (!namerx.match (ui->name) || (ui->owner && !namerx.match (*ui->owner)) || !nobadrx.match (ui->privs) || badcharrx.search (ui->pwauth) || badcharrx.search (ui->audit)) return false; sb << ui->name; sb.fmt (":%u:%u:%u:", ui->id, ui->vers, ui->gid); if (ui->owner) sb << *ui->owner; sb << ":0x" << ui->pubkey.getstr (16) << ":" << ui->privs << ":"; sb.tosuio ()->print (ui->pwauth.cstr (), ui->pwauth.len ()); sb << ":"; str priv = str2wstr (armor64 (ui->privkey.base (), ui->privkey.size ())); sb.tosuio ()->print (priv.cstr (), priv.len ()); sb << ":" << ui->audit; return true; } bool groupinfo2str (strbuf &sb, const sfsauth_groupinfo *gi) { if (!namerx.match (gi->name) || badcharrx.search (gi->audit)) return false; sb << gi->name; sb.fmt (":%u:%u:", gi->id, gi->vers); if (!printlist (sb, gi->owners, printname)) return false; sb << ":"; if (!printlist (sb, gi->members, printname)) return false; sb << ":" << gi->audit; return true; } str authdbrec2str (const sfsauth_dbrec *dbr) { strbuf sb; switch (dbr->type) { case SFSAUTH_USER: sb << "USER:"; if (userinfo2str (sb, dbr->userinfo)) return str2wstr (sb); return NULL; case SFSAUTH_GROUP: sb << "GROUP:"; if (groupinfo2str (sb, dbr->groupinfo)) return sb; return NULL; default: return NULL; } } bool str2userinfo (sfsauth_userinfo *ui, str s) { vec uv; if (split (&uv, colon, s, 11) != 10) return false; str2wstr (uv[7]); str2wstr (uv[8]); if (!namerx.match (uv[0]) || !decrx.match (uv[1]) || !decrx.match (uv[2]) || !decrx.match (uv[3]) || (uv[4].len () && !namerx.match (uv[4])) || !hexrx.match (uv[5]) || badcharrx.search (uv[6]) || badcharrx.search (uv[7]) || badcharrx.search (uv[9])) return false; { str privkey = dearmor64 (uv[8]); if (!privkey) return false; str2wstr (privkey); ui->privkey.setsize (privkey.len ()); memcpy (ui->privkey.base (), privkey, ui->privkey.size ()); } ui->name = uv[0]; if (!convertint (uv[1], &ui->id) || !convertint (uv[2], &ui->vers) || !convertint (uv[3], &ui->gid)) return false; if (uv[4].len ()) *ui->owner.alloc () = uv[4]; else ui->owner.clear (); ui->pubkey = uv[5]; ui->privs = uv[6]; ui->pwauth = uv[7]; ui->audit = uv[9]; return true; } bool str2groupinfo (sfsauth_groupinfo *gi, str s) { vec gv; if (split (&gv, colon, s, 7) != 6) return false; if (!namerx.match (gv[0]) || badcharrx.search (gv[5])) return false; gi->name = gv[0]; if (!convertint (gv[1], &gi->id) || !convertint (gv[2], &gi->vers) || !parselist (&gi->owners, gv[3], parsename) || !parselist (&gi->members, gv[4], parsename)) return false; gi->audit = gv[5]; return true; } bool str2authdbrec (sfsauth_dbrec *dbr, str s) { static rxx _userrx ("^USER:(.*)$"); rxx userrx (_userrx); static rxx grouprx ("^GROUP:(.*)$"); if (userrx.match (s)) { dbr->set_type (SFSAUTH_USER); return str2userinfo (dbr->userinfo, str2wstr (userrx[1])); } else if (grouprx.match (s)) { dbr->set_type (SFSAUTH_GROUP); return str2groupinfo (dbr->groupinfo, grouprx[1]); } else return false; }