From 4d7a5a85c3694e66c13e2cefed8176f0bbb05c3c Mon Sep 17 00:00:00 2001 From: "Maxim S. Shatskih" Date: Mon, 22 Apr 2013 17:29:16 +0400 Subject: [PATCH 1/5] git-receive-pack handler now sets USER environment variable to user logged on to client's browser (for Git hooks to work, authorization-related and maybe others) --- ReadmeThisBranch.txt | 4 ++++ WebGitNet.SharedLib/GitUtilities.cs | 13 +++++++++++++ WebGitNet/ActionResults/GitStreamResult.cs | 6 ++++-- WebGitNet/Controllers/ServiceRpcController.cs | 7 ++++--- 4 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 ReadmeThisBranch.txt diff --git a/ReadmeThisBranch.txt b/ReadmeThisBranch.txt new file mode 100644 index 0000000..9e18433 --- /dev/null +++ b/ReadmeThisBranch.txt @@ -0,0 +1,4 @@ + Updates by maxim@storagecraft.com + +1) git-receive-pack handler now sets USER environment variable to user logged on to client's browser + (for Git hooks to work, authorization-related and maybe others) diff --git a/WebGitNet.SharedLib/GitUtilities.cs b/WebGitNet.SharedLib/GitUtilities.cs index ccc9c63..27bb44a 100644 --- a/WebGitNet.SharedLib/GitUtilities.cs +++ b/WebGitNet.SharedLib/GitUtilities.cs @@ -88,6 +88,16 @@ public static string Execute(string command, string workingDir, Encoding outputE } public static Process Start(string command, string workingDir, bool redirectInput = false, bool redirectError = false, Encoding outputEncoding = null) + { + return StartInner(command, workingDir, redirectInput, redirectError, outputEncoding, null); + } + + public static Process StartWithUserName(string command, string workingDir, string userName, bool redirectInput = false, bool redirectError = false, Encoding outputEncoding = null) + { + return StartInner(command, workingDir, redirectInput, redirectError, outputEncoding, userName); + } + + private static Process StartInner(string command, string workingDir, bool redirectInput, bool redirectError, Encoding outputEncoding, string userName) { var git = WebConfigurationManager.AppSettings["GitCommand"]; var startInfo = new ProcessStartInfo(git, command) @@ -101,6 +111,9 @@ public static Process Start(string command, string workingDir, bool redirectInpu CreateNoWindow = true, }; + if (userName != null) + startInfo.EnvironmentVariables["USER"] = userName; + Process process = null, returnProcess = null; IDisposable trace = null, traceClosure = null; try diff --git a/WebGitNet/ActionResults/GitStreamResult.cs b/WebGitNet/ActionResults/GitStreamResult.cs index 002ef59..3f3a357 100644 --- a/WebGitNet/ActionResults/GitStreamResult.cs +++ b/WebGitNet/ActionResults/GitStreamResult.cs @@ -18,8 +18,9 @@ public class GitStreamResult : ActionResult private readonly string commandFormat; private readonly string action; private readonly string repoPath; + private readonly string userName; - public GitStreamResult(string commandFormat, string action, string repoPath) + public GitStreamResult(string commandFormat, string action, string repoPath, string userName = null) { if (string.IsNullOrEmpty(commandFormat)) { @@ -41,6 +42,7 @@ public GitStreamResult(string commandFormat, string action, string repoPath) } this.repoPath = repoPath; + this.userName = userName; } public override void ExecuteResult(ControllerContext context) @@ -52,7 +54,7 @@ public override void ExecuteResult(ControllerContext context) response.ContentType = "application/x-git-" + this.action + "-result"; response.BufferOutput = false; - using (var git = GitUtilities.Start(string.Format(this.commandFormat, this.action), this.repoPath, redirectInput: true)) + using (var git = GitUtilities.StartWithUserName(string.Format(this.commandFormat, this.action), this.repoPath, this.userName, redirectInput: true)) { var readThread = new Thread(() => { diff --git a/WebGitNet/Controllers/ServiceRpcController.cs b/WebGitNet/Controllers/ServiceRpcController.cs index 33efa9d..c33af36 100644 --- a/WebGitNet/Controllers/ServiceRpcController.cs +++ b/WebGitNet/Controllers/ServiceRpcController.cs @@ -22,10 +22,11 @@ public ActionResult UploadPack(string url) [HttpPost] public ActionResult ReceivePack(string url) { - return this.ServiceRpc(url, "receive-pack"); + string userName = User.Identity.Name; + return this.ServiceRpc(url, "receive-pack", userName); } - private ActionResult ServiceRpc(string url, string action) + private ActionResult ServiceRpc(string url, string action, string userName = null) { var resourceInfo = this.FileManager.GetResourceInfo(url); if (resourceInfo.FileSystemInfo == null) @@ -35,7 +36,7 @@ private ActionResult ServiceRpc(string url, string action) var repoPath = ((FileInfo)resourceInfo.FileSystemInfo).Directory.FullName; - return new GitStreamResult("{0} --stateless-rpc .", action, repoPath); + return new GitStreamResult("{0} --stateless-rpc .", action, repoPath, userName); } } } From b5b38c092bba19d9a432ff0385968e665c68f89d Mon Sep 17 00:00:00 2001 From: "Maxim S. Shatskih" Date: Wed, 24 Apr 2013 22:41:53 +0400 Subject: [PATCH 2/5] Now shows the logged-on user name everywhere --- ReadmeThisBranch.txt | 1 + WebGitNet/Views/Shared/_Layout.cshtml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/ReadmeThisBranch.txt b/ReadmeThisBranch.txt index 9e18433..25e4aeb 100644 --- a/ReadmeThisBranch.txt +++ b/ReadmeThisBranch.txt @@ -2,3 +2,4 @@ 1) git-receive-pack handler now sets USER environment variable to user logged on to client's browser (for Git hooks to work, authorization-related and maybe others) +2) now shows the logged-on user name everywhere diff --git a/WebGitNet/Views/Shared/_Layout.cshtml b/WebGitNet/Views/Shared/_Layout.cshtml index fa555f3..642191c 100644 --- a/WebGitNet/Views/Shared/_Layout.cshtml +++ b/WebGitNet/Views/Shared/_Layout.cshtml @@ -61,6 +61,9 @@ } } + From 291a39dd90c239a36a2dc9c05db31d84eb2c1fd8 Mon Sep 17 00:00:00 2001 From: "Maxim S. Shatskih" Date: Thu, 25 Apr 2013 23:53:04 +0400 Subject: [PATCH 3/5] Now fails git-receive-pack if the logged-on user is in the "limited readers" group --- ReadmeThisBranch.txt | 1 + WebGitNet.SharedLib/SharedControllerBase.cs | 28 +++++++++++++++++++ WebGitNet/Controllers/ServiceRpcController.cs | 2 ++ WebGitNet/Web.config | 1 + 4 files changed, 32 insertions(+) diff --git a/ReadmeThisBranch.txt b/ReadmeThisBranch.txt index 25e4aeb..317a275 100644 --- a/ReadmeThisBranch.txt +++ b/ReadmeThisBranch.txt @@ -3,3 +3,4 @@ 1) git-receive-pack handler now sets USER environment variable to user logged on to client's browser (for Git hooks to work, authorization-related and maybe others) 2) now shows the logged-on user name everywhere +3) now fails git-receive-pack if the logged-on user is in the "limited readers" group diff --git a/WebGitNet.SharedLib/SharedControllerBase.cs b/WebGitNet.SharedLib/SharedControllerBase.cs index d63e4c6..6127aa9 100644 --- a/WebGitNet.SharedLib/SharedControllerBase.cs +++ b/WebGitNet.SharedLib/SharedControllerBase.cs @@ -14,6 +14,7 @@ public abstract partial class SharedControllerBase : Controller { private readonly FileManager fileManager; private readonly BreadCrumbTrail breadCrumbs; + private bool areWeLimitedReader; public SharedControllerBase() { @@ -25,6 +26,13 @@ public SharedControllerBase() ViewBag.BreadCrumbs = this.breadCrumbs; } + protected override void Initialize(System.Web.Routing.RequestContext requestContext) + { + base.Initialize(requestContext); + // Set our user access rights flags + areWeLimitedReader = areWeInReadOnlyLimitedGroup(); + } + protected void AddRepoBreadCrumb(string repo) { this.BreadCrumbs.Append("Browse", "ViewRepo", repo, new { repo }); @@ -45,5 +53,25 @@ public BreadCrumbTrail BreadCrumbs return this.breadCrumbs; } } + + protected bool AreWeLimitedReader + { + get + { + return this.areWeLimitedReader; + } + } + + private bool areWeInConfigGroup(string groupKeyName) + { + var clientPrincipal = (System.Security.Principal.WindowsPrincipal)User; + var groupName = WebConfigurationManager.AppSettings[groupKeyName]; + return clientPrincipal.IsInRole(groupName); + } + + private bool areWeInReadOnlyLimitedGroup() + { + return areWeInConfigGroup("ReadOnlyLimitedGroupName"); + } } } diff --git a/WebGitNet/Controllers/ServiceRpcController.cs b/WebGitNet/Controllers/ServiceRpcController.cs index c33af36..f2f5333 100644 --- a/WebGitNet/Controllers/ServiceRpcController.cs +++ b/WebGitNet/Controllers/ServiceRpcController.cs @@ -22,6 +22,8 @@ public ActionResult UploadPack(string url) [HttpPost] public ActionResult ReceivePack(string url) { + if (AreWeLimitedReader) + return new HttpStatusCodeResult(403, "You do not have permission to push to this repo"); string userName = User.Identity.Name; return this.ServiceRpc(url, "receive-pack", userName); } diff --git a/WebGitNet/Web.config b/WebGitNet/Web.config index 7f336b0..542159d 100644 --- a/WebGitNet/Web.config +++ b/WebGitNet/Web.config @@ -3,6 +3,7 @@ + From 72f0026ecec2d5c0c7c824beb3732a26f96a6e9a Mon Sep 17 00:00:00 2001 From: "Maxim S. Shatskih" Date: Sat, 11 May 2013 14:00:01 +0400 Subject: [PATCH 4/5] Now prohibits repository creation if the logged-on user is not in the "repo creators" group --- WebGitNet.SharedLib/SharedControllerBase.cs | 15 +++++++++++++++ WebGitNet/Controllers/ManageController.cs | 2 ++ WebGitNet/Views/Browse/Index.cshtml | 13 ++++++++++++- WebGitNet/Views/Manage/Create.cshtml | 12 ++++++++++++ WebGitNet/Views/Shared/_Layout.cshtml | 13 ++++++++++++- WebGitNet/Web.config | 1 + 6 files changed, 54 insertions(+), 2 deletions(-) diff --git a/WebGitNet.SharedLib/SharedControllerBase.cs b/WebGitNet.SharedLib/SharedControllerBase.cs index 6127aa9..595ba1f 100644 --- a/WebGitNet.SharedLib/SharedControllerBase.cs +++ b/WebGitNet.SharedLib/SharedControllerBase.cs @@ -15,6 +15,7 @@ public abstract partial class SharedControllerBase : Controller private readonly FileManager fileManager; private readonly BreadCrumbTrail breadCrumbs; private bool areWeLimitedReader; + private bool areWeRepoCreator; public SharedControllerBase() { @@ -31,6 +32,7 @@ protected override void Initialize(System.Web.Routing.RequestContext requestCont base.Initialize(requestContext); // Set our user access rights flags areWeLimitedReader = areWeInReadOnlyLimitedGroup(); + areWeRepoCreator = areWeInRepoCreatorGroup(); } protected void AddRepoBreadCrumb(string repo) @@ -62,6 +64,14 @@ protected bool AreWeLimitedReader } } + public bool AreWeRepoCreator + { + get + { + return this.areWeRepoCreator; + } + } + private bool areWeInConfigGroup(string groupKeyName) { var clientPrincipal = (System.Security.Principal.WindowsPrincipal)User; @@ -73,5 +83,10 @@ private bool areWeInReadOnlyLimitedGroup() { return areWeInConfigGroup("ReadOnlyLimitedGroupName"); } + + private bool areWeInRepoCreatorGroup() + { + return areWeInConfigGroup("RepoCreatorsGroupName"); + } } } diff --git a/WebGitNet/Controllers/ManageController.cs b/WebGitNet/Controllers/ManageController.cs index 2af6d24..ef8befb 100644 --- a/WebGitNet/Controllers/ManageController.cs +++ b/WebGitNet/Controllers/ManageController.cs @@ -32,6 +32,8 @@ public ActionResult Create(CreateRepoRequest request) if (ModelState.IsValid) { + if( !AreWeRepoCreator ) + return new HttpStatusCodeResult(403, "You do not have permission to create repositories"); var invalid = Path.GetInvalidFileNameChars(); if (request.RepoName.Any(c => invalid.Contains(c))) diff --git a/WebGitNet/Views/Browse/Index.cshtml b/WebGitNet/Views/Browse/Index.cshtml index 3132b33..f7c3f62 100644 --- a/WebGitNet/Views/Browse/Index.cshtml +++ b/WebGitNet/Views/Browse/Index.cshtml @@ -4,6 +4,10 @@ var archived = (bool)ViewBag.Archived; ViewBag.Title = archived ? "Archived Repositories" : "Repositories"; } +@{ + var cntr = (WebGitNet.SharedControllerBase)ViewContext.Controller; + bool WeCanCreateRepo = cntr.AreWeRepoCreator; +}
@using (Html.BeginForm("Search", "Search", FormMethod.Get, new { @class = "form form-search" })) @@ -28,7 +32,14 @@

- Create a new repo + @if (WeCanCreateRepo) + { + Create a new repo + } + else + { + Cannot create repo + } @if (archived) { View current repos diff --git a/WebGitNet/Views/Manage/Create.cshtml b/WebGitNet/Views/Manage/Create.cshtml index 16fa2b2..cc4a4d1 100644 --- a/WebGitNet/Views/Manage/Create.cshtml +++ b/WebGitNet/Views/Manage/Create.cshtml @@ -2,6 +2,18 @@ @{ ViewBag.Title = "Create Repo"; } +@{ + var ctx = Context.ApplicationInstance.Context; + var cntr = (WebGitNet.Controllers.ManageController)ViewContext.Controller; + if( !cntr.AreWeRepoCreator ) + { + var httpRsp = ctx.Response; + httpRsp.StatusCode = 403; + httpRsp.StatusDescription = "You are not allowed to create repositories"; + httpRsp.SubStatusCode = 3; + return; + } +}

diff --git a/WebGitNet/Views/Shared/_Layout.cshtml b/WebGitNet/Views/Shared/_Layout.cshtml index 642191c..6b69aed 100644 --- a/WebGitNet/Views/Shared/_Layout.cshtml +++ b/WebGitNet/Views/Shared/_Layout.cshtml @@ -2,6 +2,10 @@ @{ var breadcrumbs = (BreadCrumbTrail)ViewBag.BreadCrumbs; } +@{ + var cntr = (WebGitNet.SharedControllerBase)ViewContext.Controller; + bool WeCanCreateRepo = cntr.AreWeRepoCreator; +} @@ -28,7 +32,14 @@ @ViewBag.Title