Browse Source

push + pull now works with reverse proxy + basic auth on apache 2.4

Gogs 3 years ago
parent
commit
37eec6c9b7
1 changed files with 75 additions and 62 deletions
  1. 75 62
      routers/repo/http.go

+ 75 - 62
routers/repo/http.go

@@ -83,85 +83,98 @@ func HTTP(ctx *context.Context) {
83 83
 
84 84
 	// check access
85 85
 	if askAuth {
86
-		authHead := ctx.Req.Header.Get("Authorization")
87
-		if len(authHead) == 0 {
88
-			ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=\".\"")
89
-			ctx.Error(http.StatusUnauthorized)
90
-			return
91
-		}
92
-
93
-		auths := strings.Fields(authHead)
94
-		// currently check basic auth
95
-		// TODO: support digit auth
96
-		// FIXME: middlewares/context.go did basic auth check already,
97
-		// maybe could use that one.
98
-		if len(auths) != 2 || auths[0] != "Basic" {
99
-			ctx.HandleText(http.StatusUnauthorized, "no basic auth and digit auth")
100
-			return
101
-		}
102
-		authUsername, authPasswd, err = base.BasicAuthDecode(auths[1])
103
-		if err != nil {
104
-			ctx.HandleText(http.StatusUnauthorized, "no basic auth and digit auth")
105
-			return
106
-		}
107
-
108
-		authUser, err = models.UserSignIn(authUsername, authPasswd)
109
-		if err != nil {
110
-			if !models.IsErrUserNotExist(err) {
111
-				ctx.Handle(http.StatusInternalServerError, "UserSignIn error: %v", err)
86
+		if setting.Service.EnableReverseProxyAuth {
87
+			authUsername = ctx.Req.Header.Get(setting.ReverseProxyAuthUser)
88
+			if len(authUsername) == 0 {
89
+				ctx.HandleText(401, "reverse proxy login error. authUsername empty")
112 90
 				return
113 91
 			}
114
-
115
-			// Assume username now is a token.
116
-			token, err := models.GetAccessTokenBySHA(authUsername)
92
+			authUser, err = models.GetUserByName(authUsername)
117 93
 			if err != nil {
118
-				if models.IsErrAccessTokenNotExist(err) || models.IsErrAccessTokenEmpty(err) {
119
-					ctx.HandleText(http.StatusUnauthorized, "invalid token")
120
-				} else {
121
-					ctx.Handle(http.StatusInternalServerError, "GetAccessTokenBySha", err)
122
-				}
94
+				ctx.HandleText(401, "reverse proxy login error, got error while running GetUserByName")
95
+				return
96
+			}
97
+		}else{
98
+			authHead := ctx.Req.Header.Get("Authorization")
99
+			if len(authHead) == 0 {
100
+				ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=\".\"")
101
+				ctx.Error(http.StatusUnauthorized)
123 102
 				return
124 103
 			}
125
-			token.Updated = time.Now()
126
-			if err = models.UpdateAccessToken(token); err != nil {
127
-				ctx.Handle(http.StatusInternalServerError, "UpdateAccessToken", err)
104
+
105
+			auths := strings.Fields(authHead)
106
+			// currently check basic auth
107
+			// TODO: support digit auth
108
+			// FIXME: middlewares/context.go did basic auth check already,
109
+			// maybe could use that one.
110
+			if len(auths) != 2 || auths[0] != "Basic" {
111
+				ctx.HandleText(http.StatusUnauthorized, "no basic auth and digit auth")
112
+				return
128 113
 			}
129
-			authUser, err = models.GetUserByID(token.UID)
114
+			authUsername, authPasswd, err = base.BasicAuthDecode(auths[1])
130 115
 			if err != nil {
131
-				ctx.Handle(http.StatusInternalServerError, "GetUserByID", err)
116
+				ctx.HandleText(http.StatusUnauthorized, "no basic auth and digit auth")
132 117
 				return
133 118
 			}
134
-		}
135 119
 
136
-		if !isPublicPull {
137
-			var tp = models.AccessModeWrite
138
-			if isPull {
139
-				tp = models.AccessModeRead
120
+			authUser, err = models.UserSignIn(authUsername, authPasswd)
121
+			if err != nil {
122
+				if !models.IsErrUserNotExist(err) {
123
+					ctx.Handle(http.StatusInternalServerError, "UserSignIn error: %v", err)
124
+					return
125
+				}
126
+
127
+				// Assume username now is a token.
128
+				token, err := models.GetAccessTokenBySHA(authUsername)
129
+				if err != nil {
130
+					if models.IsErrAccessTokenNotExist(err) || models.IsErrAccessTokenEmpty(err) {
131
+						ctx.HandleText(http.StatusUnauthorized, "invalid token")
132
+					} else {
133
+						ctx.Handle(http.StatusInternalServerError, "GetAccessTokenBySha", err)
134
+					}
135
+					return
136
+				}
137
+				token.Updated = time.Now()
138
+				if err = models.UpdateAccessToken(token); err != nil {
139
+					ctx.Handle(http.StatusInternalServerError, "UpdateAccessToken", err)
140
+				}
141
+				authUser, err = models.GetUserByID(token.UID)
142
+				if err != nil {
143
+					ctx.Handle(http.StatusInternalServerError, "GetUserByID", err)
144
+					return
145
+				}
140 146
 			}
141 147
 
142
-			has, err := models.HasAccess(authUser, repo, tp)
143
-			if err != nil {
144
-				ctx.Handle(http.StatusInternalServerError, "HasAccess", err)
145
-				return
146
-			} else if !has {
147
-				if tp == models.AccessModeRead {
148
-					has, err = models.HasAccess(authUser, repo, models.AccessModeWrite)
149
-					if err != nil {
150
-						ctx.Handle(http.StatusInternalServerError, "HasAccess2", err)
151
-						return
152
-					} else if !has {
148
+			if !isPublicPull {
149
+				var tp = models.AccessModeWrite
150
+				if isPull {
151
+					tp = models.AccessModeRead
152
+				}
153
+
154
+				has, err := models.HasAccess(authUser, repo, tp)
155
+				if err != nil {
156
+					ctx.Handle(http.StatusInternalServerError, "HasAccess", err)
157
+					return
158
+				} else if !has {
159
+					if tp == models.AccessModeRead {
160
+						has, err = models.HasAccess(authUser, repo, models.AccessModeWrite)
161
+						if err != nil {
162
+							ctx.Handle(http.StatusInternalServerError, "HasAccess2", err)
163
+							return
164
+						} else if !has {
165
+							ctx.HandleText(http.StatusForbidden, "User permission denied")
166
+							return
167
+						}
168
+					} else {
153 169
 						ctx.HandleText(http.StatusForbidden, "User permission denied")
154 170
 						return
155 171
 					}
156
-				} else {
157
-					ctx.HandleText(http.StatusForbidden, "User permission denied")
158
-					return
159 172
 				}
160
-			}
161 173
 
162
-			if !isPull && repo.IsMirror {
163
-				ctx.HandleText(http.StatusForbidden, "mirror repository is read-only")
164
-				return
174
+				if !isPull && repo.IsMirror {
175
+					ctx.HandleText(http.StatusForbidden, "mirror repository is read-only")
176
+					return
177
+				}
165 178
 			}
166 179
 		}
167 180
 	}