public static int StartDaemon(ClientInfo clientInfo) { IOStream stream = clientInfo.IoStream; Options options = clientInfo.Options; options.amDaemon = true; stream.IOPrintf("@RSYNCD: " + options.protocolVersion + "\n"); string line = stream.ReadLine(); try { options.remoteProtocol = Int32.Parse(line.Substring(9, 2)); } catch { options.remoteProtocol = 0; } bool isValidstring = line.StartsWith("@RSYNCD: ") && line.EndsWith("\n") && options.remoteProtocol > 0; if (!isValidstring) { stream.IOPrintf("@ERROR: protocol startup error\n"); return(-1); } if (options.protocolVersion > options.remoteProtocol) { options.protocolVersion = options.remoteProtocol; } line = stream.ReadLine(); if (line.CompareTo("#list\n") == 0) { ClientServer.SendListing(stream); return(-1); } if (line[0] == '#') { stream.IOPrintf("@ERROR: Unknown command '" + line.Replace("\n", String.Empty) + "'\n"); return(-1); } int i = config.GetNumberModule(line.Replace("\n", String.Empty)); if (i < 0) { stream.IOPrintf("@ERROR: Unknown module " + line); MainClass.Exit("@ERROR: Unknown module " + line, clientInfo); } options.doStats = true; options.ModuleId = i; ClientServer.RsyncModule(clientInfo, i); clientInfo.IoStream.Close(); return(1); }
public static int RsyncModule(ClientInfo cInfo, int moduleNumber) { string path = Daemon.config.GetModule(moduleNumber).Path; string name = Daemon.config.GetModuleName(moduleNumber); IOStream f = cInfo.IoStream; Options options = cInfo.Options; string[] args = new string[Options.MAX_ARGS]; int argc = 0, maxargs = Options.MAX_ARGS; string line = ""; if (path[0] == '/') { path = path.Remove(0, 1); } path = path.Replace("\n", ""); Access ac = new Access(); if (!ac.AllowAccess(options.remoteAddr, options.remoteHost, Daemon.config.GetHostsAllow(moduleNumber), Daemon.config.GetHostsDeny(moduleNumber))) { Log.Write("rsync denied on module " + name + " from " + options.remoteHost + " (" + options.remoteAddr + ")"); f.IOPrintf("@ERROR: access denied to " + name + " from " + options.remoteHost + " (" + options.remoteAddr + ")\n"); return(-1); } if (!Authentication.AuthServer(cInfo, moduleNumber, options.remoteAddr, "@RSYNCD: AUTHREQD ")) { Log.Write("auth failed on module " + name + " from " + options.remoteHost + " (" + options.remoteAddr + ")\n"); f.IOPrintf("@ERROR: auth failed on module " + name + "\n"); return(-1); } // TODO: path length if (FileSystem.Directory.Exists(path)) { f.IOPrintf("@RSYNCD: OK\n"); } else { try { // TODO: path length FileSystem.Directory.CreateDirectory(path); f.IOPrintf("@RSYNCD: OK\n"); } catch (Exception) { f.IOPrintf("@ERROR: Path not found\n"); MainClass.Exit("@ERROR: Path not found: " + path, cInfo); } } options.amServer = true; //to fix error in SetupProtocol options.dir = path; while (true) { line = f.ReadLine(); line = line.Substring(0, line.Length - 1); if (line.CompareTo("") == 0) { break; } if (argc == maxargs) { maxargs += Options.MAX_ARGS; MapFile.ReallocArrayString(ref args, maxargs); } args[argc++] = line; } args[argc++] = path; options.verbose = 0; int argsNotUsed = CommandLineParser.ParseArguments(args, options); if (argsNotUsed == -1) { MainClass.Exit("Error parsing options", cInfo); } string[] args2 = new string[argsNotUsed]; for (int i = 0; i < argsNotUsed; i++) { args2[i] = args[args.Length - argsNotUsed + i]; } MainClass.SetupProtocol(cInfo); f.IOStartMultiplexOut(); Daemon.StartServer(cInfo, args2); return(-1); }
public static bool AuthServer(ClientInfo cInfo, int moduleNumber, string addr, string leader) { string users = Daemon.config.GetAuthUsers(moduleNumber).Trim(); string challenge; string b64_challenge; IOStream f = cInfo.IoStream; string line; string user = ""; string secret = ""; string pass = ""; string pass2 = ""; string[] listUsers; string tok = ""; /* if no auth list then allow anyone in! */ if (users == null || users.CompareTo("") == 0) { return(true); } challenge = gen_challenge(addr, cInfo.Options); b64_challenge = base64_encode(challenge); f.IOPrintf(leader + b64_challenge + "\n"); line = f.ReadLine(); if (line.IndexOf(' ') > 0) { user = line.Substring(0, line.IndexOf(' ')); pass = line.Substring(line.IndexOf(' ')).Trim('\n').Trim(); } else { return(false); } listUsers = users.Split(','); for (int i = 0; i < listUsers.Length; i++) { tok = listUsers[i]; if (user.CompareTo(tok) == 0) { break; } tok = null; } if (tok == null || tok.CompareTo("") == 0) { return(false); } if ((secret = GetSecret(moduleNumber, user)) == null) { return(false); } pass2 = generate_hash(secret, b64_challenge, cInfo.Options); if (pass.CompareTo(pass2) == 0) { return(true); } return(false); }
public static int StartInbandExchange(string user, string path, ClientInfo cInfo, int argc) { Options options = cInfo.Options; IOStream f = cInfo.IoStream; string[] sargs = new string[Options.MAX_ARGS]; int sargc = options.ServerOptions(sargs); sargs[sargc++] = "."; //if(path != null && path.Length>0) //sargs[sargc++] = path; if (argc == 0 && !options.amSender) { options.listOnly = true; } if (path[0] == '/') { Log.WriteLine("ERROR: The remote path must start with a module name"); return(-1); } f.IOPrintf("@RSYNCD: " + options.protocolVersion + "\n"); string line = f.ReadLine(); try { options.remoteProtocol = Int32.Parse(line.Substring(9, 2)); } catch { options.remoteProtocol = 0; } bool isValidstring = line.StartsWith("@RSYNCD: ") && line.EndsWith("\n") && options.remoteProtocol > 0; if (!isValidstring) { f.IOPrintf("@ERROR: protocol startup error\n"); return(-1); } if (options.protocolVersion > options.remoteProtocol) { options.protocolVersion = options.remoteProtocol; } f.IOPrintf(path + "\n"); while (true) { line = f.ReadLine(); if (line.CompareTo("@RSYNCD: OK\n") == 0) { break; } if (line.Length > 18 && line.Substring(0, 18).CompareTo("@RSYNCD: AUTHREQD ") == 0) { string pass = String.Empty; if (user.IndexOf(':') != -1) { pass = user.Substring(user.IndexOf(':') + 1); user = user.Substring(0, user.IndexOf(':')); } f.IOPrintf(user + " " + Authentication.AuthorizeClient(user, pass, line.Substring(18).Replace("\n", String.Empty), options) + "\n"); continue; } if (line.CompareTo("@RSYNCD: EXIT\n") == 0) { MainClass.Exit("@RSYNCD: EXIT", null); } if (line.StartsWith("@ERROR: ")) { MainClass.Exit("Server: " + line.Replace("\n", String.Empty), null); } } for (int i = 0; i < sargc; i++) { f.IOPrintf(sargs[i] + "\n"); } f.IOPrintf("\n"); return(0); }
/// <summary> /// Server-side authorization check /// </summary> /// <param name="clientInfo"></param> /// <param name="moduleNumber"></param> /// <param name="addr"></param> /// <param name="leader"></param> /// <returns></returns> public static bool AuthorizeServer(ClientInfo clientInfo, int moduleNumber, string addr, string leader) { string users = Daemon.config.GetAuthUsers(moduleNumber).Trim(); //string challenge; string b64Challenge; IOStream ioStream = clientInfo.IoStream; string line; string user = String.Empty; string secret = String.Empty; string pass = String.Empty; string pass2 = String.Empty; string[] listUsers; string token = String.Empty; /* if no auth list then allow anyone in! */ if (string.IsNullOrEmpty(users)) { return(true); } b64Challenge = Base64Encode(GenerateChallenge(addr, clientInfo.Options)); ioStream.IOPrintf(leader + b64Challenge + "\n"); line = ioStream.ReadLine(); if (line.IndexOf(' ') > 0) { user = line.Substring(0, line.IndexOf(' ')); pass = line.Substring(line.IndexOf(' ')).Trim('\n').Trim(); } else { return(false); } listUsers = users.Split(','); for (int i = 0; i < listUsers.Length; i++) { token = listUsers[i]; if (user.Equals(token)) { break; } token = null; } if (string.IsNullOrEmpty(token)) { return(false); } if ((secret = GetSecret(moduleNumber, user)) == null) { return(false); } pass2 = GenerateHash(secret, b64Challenge, clientInfo.Options); if (pass.Equals(pass2)) { return(true); } return(false); }