add ssl support for web
This commit is contained in:
		
							parent
							
								
									75db79b4b6
								
							
						
					
					
						commit
						493b0c5ac2
					
				
					 4 changed files with 118 additions and 7 deletions
				
			
		|  | @ -12,10 +12,13 @@ LANG_IGNS = Google Go|C|C++|Python|Ruby|C Sharp | ||||||
| LICENSES = Apache v2 License|GPL v2|MIT License|Affero GPL|Artistic License 2.0|BSD (3-Clause) License | LICENSES = Apache v2 License|GPL v2|MIT License|Affero GPL|Artistic License 2.0|BSD (3-Clause) License | ||||||
| 
 | 
 | ||||||
| [server] | [server] | ||||||
|  | PROTOCOL = http | ||||||
| DOMAIN = localhost | DOMAIN = localhost | ||||||
| ROOT_URL = http://%(DOMAIN)s:%(HTTP_PORT)s/ | ROOT_URL = %(PROTOCOL)://%(DOMAIN)s:%(HTTP_PORT)s/ | ||||||
| HTTP_ADDR =  | HTTP_ADDR =  | ||||||
| HTTP_PORT = 3000 | HTTP_PORT = 3000 | ||||||
|  | CERT_FILE = cert.pem | ||||||
|  | KEY_FILE = key.pem | ||||||
| 
 | 
 | ||||||
| [database] | [database] | ||||||
| ; Either "mysql", "postgres" or "sqlite3"(binary release only), it's your choice | ; Either "mysql", "postgres" or "sqlite3"(binary release only), it's your choice | ||||||
|  |  | ||||||
|  | @ -5,6 +5,8 @@ | ||||||
| package repo | package repo | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"encoding/base64" | ||||||
|  | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"path" | 	"path" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
|  | @ -237,15 +239,105 @@ func SingleDownload(ctx *middleware.Context, params martini.Params) { | ||||||
| 	ctx.Res.Write(data) | 	ctx.Res.Write(data) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func Http(ctx *middleware.Context, params martini.Params) { | func basicEncode(username, password string) string { | ||||||
| 	// TODO: access check
 | 	auth := username + ":" + password | ||||||
|  | 	return base64.StdEncoding.EncodeToString([]byte(auth)) | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|  | func basicDecode(encoded string) (user string, name string, err error) { | ||||||
|  | 	var s []byte | ||||||
|  | 	s, err = base64.StdEncoding.DecodeString(encoded) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	a := strings.Split(string(s), ":") | ||||||
|  | 	if len(a) == 2 { | ||||||
|  | 		user, name = a[0], a[1] | ||||||
|  | 	} else { | ||||||
|  | 		err = errors.New("decode failed") | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func authRequired(ctx *middleware.Context) { | ||||||
|  | 	ctx.ResponseWriter.Header().Set("WWW-Authenticate", `Basic realm="Gogs Auth"`) | ||||||
|  | 	ctx.Data["ErrorMsg"] = "no basic auth and digit auth" | ||||||
|  | 	ctx.HTML(401, fmt.Sprintf("status/401")) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func Http(ctx *middleware.Context, params martini.Params) { | ||||||
| 	username := params["username"] | 	username := params["username"] | ||||||
| 	reponame := params["reponame"] | 	reponame := params["reponame"] | ||||||
| 	if strings.HasSuffix(reponame, ".git") { | 	if strings.HasSuffix(reponame, ".git") { | ||||||
| 		reponame = reponame[:len(reponame)-4] | 		reponame = reponame[:len(reponame)-4] | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	repoUser, err := models.GetUserByName(username) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ctx.Handle(500, "repo.GetUserByName", nil) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	repo, err := models.GetRepositoryByName(repoUser.Id, reponame) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ctx.Handle(500, "repo.GetRepositoryByName", nil) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	isPull := webdav.IsPullMethod(ctx.Req.Method) | ||||||
|  | 	var askAuth = !(!repo.IsPrivate && isPull) | ||||||
|  | 
 | ||||||
|  | 	//authRequired(ctx)
 | ||||||
|  | 	//return
 | ||||||
|  | 
 | ||||||
|  | 	// check access
 | ||||||
|  | 	if askAuth { | ||||||
|  | 		// check digit auth
 | ||||||
|  | 
 | ||||||
|  | 		// check basic auth
 | ||||||
|  | 		baHead := ctx.Req.Header.Get("Authorization") | ||||||
|  | 		if baHead != "" { | ||||||
|  | 			auths := strings.Fields(baHead) | ||||||
|  | 			if len(auths) != 2 || auths[0] != "Basic" { | ||||||
|  | 				ctx.Handle(401, "no basic auth and digit auth", nil) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			authUsername, passwd, err := basicDecode(auths[1]) | ||||||
|  | 			if err != nil { | ||||||
|  | 				ctx.Handle(401, "no basic auth and digit auth", nil) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			authUser, err := models.GetUserByName(authUsername) | ||||||
|  | 			if err != nil { | ||||||
|  | 				ctx.Handle(401, "no basic auth and digit auth", nil) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			newUser := &models.User{Passwd: passwd} | ||||||
|  | 			newUser.EncodePasswd() | ||||||
|  | 			if authUser.Passwd != newUser.Passwd { | ||||||
|  | 				ctx.Handle(401, "no basic auth and digit auth", nil) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			var tp = models.AU_WRITABLE | ||||||
|  | 			if isPull { | ||||||
|  | 				tp = models.AU_READABLE | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			has, err := models.HasAccess(authUsername, username+"/"+reponame, tp) | ||||||
|  | 			if err != nil || !has { | ||||||
|  | 				ctx.Handle(401, "no basic auth and digit auth", nil) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			authRequired(ctx) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	prefix := path.Join("/", username, params["reponame"]) | 	prefix := path.Join("/", username, params["reponame"]) | ||||||
| 	server := webdav.NewServer( | 	server := webdav.NewServer( | ||||||
| 		models.RepoPath(username, reponame), | 		models.RepoPath(username, reponame), | ||||||
|  |  | ||||||
							
								
								
									
										6
									
								
								templates/status/401.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								templates/status/401.tmpl
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | ||||||
|  | {{template "base/head" .}} | ||||||
|  | {{template "base/navbar" .}} | ||||||
|  | <div class="container"> | ||||||
|  | 	401 Unauthorized | ||||||
|  | </div> | ||||||
|  | {{template "base/footer" .}} | ||||||
							
								
								
									
										18
									
								
								web.go
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								web.go
									
									
									
									
									
								
							|  | @ -169,12 +169,22 @@ func runWeb(*cli.Context) { | ||||||
| 	// Not found handler.
 | 	// Not found handler.
 | ||||||
| 	m.NotFound(routers.NotFound) | 	m.NotFound(routers.NotFound) | ||||||
| 
 | 
 | ||||||
|  | 	protocol := base.Cfg.MustValue("server", "PROTOCOL", "http") | ||||||
| 	listenAddr := fmt.Sprintf("%s:%s", | 	listenAddr := fmt.Sprintf("%s:%s", | ||||||
| 		base.Cfg.MustValue("server", "HTTP_ADDR"), | 		base.Cfg.MustValue("server", "HTTP_ADDR"), | ||||||
| 		base.Cfg.MustValue("server", "HTTP_PORT", "3000")) | 		base.Cfg.MustValue("server", "HTTP_PORT", "3000")) | ||||||
| 	log.Info("Listen: %s", listenAddr) | 
 | ||||||
| 	if err := http.ListenAndServe(listenAddr, m); err != nil { | 	if protocol == "http" { | ||||||
| 		fmt.Println(err.Error()) | 		log.Info("Listen: http://%s", listenAddr) | ||||||
| 		//log.Critical(err.Error()) // not working now
 | 		if err := http.ListenAndServe(listenAddr, m); err != nil { | ||||||
|  | 			fmt.Println(err.Error()) | ||||||
|  | 			//log.Critical(err.Error()) // not working now
 | ||||||
|  | 		} | ||||||
|  | 	} else if protocol == "https" { | ||||||
|  | 		log.Info("Listen: https://%s", listenAddr) | ||||||
|  | 		if err := http.ListenAndServeTLS(listenAddr, base.Cfg.MustValue("server", "CERT_FILE"), | ||||||
|  | 			base.Cfg.MustValue("server", "KEY_FILE"), m); err != nil { | ||||||
|  | 			fmt.Println(err.Error()) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue