diff --git a/db/migrations/20160211211220_0.1.2_add_ignore_cert_errors.sql b/db/migrations/20160211211220_0.1.2_add_ignore_cert_errors.sql new file mode 100644 index 00000000..f66183f5 --- /dev/null +++ b/db/migrations/20160211211220_0.1.2_add_ignore_cert_errors.sql @@ -0,0 +1,8 @@ + +-- +goose Up +-- SQL in section 'Up' is executed when this migration is applied +ALTER TABLE smtp ADD COLUMN ignore_cert_errors BOOLEAN; + +-- +goose Down +-- SQL section 'Down' is executed when this migration is rolled back + diff --git a/models/smtp.go b/models/smtp.go index c93bd872..cf6d69d1 100644 --- a/models/smtp.go +++ b/models/smtp.go @@ -4,12 +4,13 @@ import "errors" // SMTP contains the attributes needed to handle the sending of campaign emails type SMTP struct { - SMTPId int64 `json:"-" gorm:"column:smtp_id; primary_key:yes"` - CampaignId int64 `json:"-" gorm:"column:campaign_id"` - Host string `json:"host"` - Username string `json:"username,omitempty"` - Password string `json:"password,omitempty" sql:"-"` - FromAddress string `json:"from_address"` + SMTPId int64 `json:"-" gorm:"column:smtp_id; primary_key:yes"` + CampaignId int64 `json:"-" gorm:"column:campaign_id"` + Host string `json:"host"` + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty" sql:"-"` + FromAddress string `json:"from_address"` + IgnoreCertErrors bool `json:"ignore_cert_errors"` } // ErrFromAddressNotSpecified is thrown when there is no "From" address diff --git a/static/css/main.css b/static/css/main.css index 64c02f39..dcf13bb9 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -374,6 +374,9 @@ table.dataTable thead .sorting_desc:after { content: "\f0dd" !important; opacity: .8 !important; } +td.details-control{ + cursor:pointer; +} .timeline{ text-align:left; background-color:#ffffff; @@ -445,6 +448,10 @@ table.dataTable thead .sorting_desc:after { margin-top: 10px; margin-bottom: 10px; } -.timeline-event-table{ +.timeline-event-results{ + font-size:16px; display:none; } +.tooltip-inner { + width:300px !important; +} diff --git a/static/js/app/campaign_results.js b/static/js/app/campaign_results.js index efddfd36..efba5e8b 100644 --- a/static/js/app/campaign_results.js +++ b/static/js/app/campaign_results.js @@ -139,21 +139,28 @@ function renderTimeline(data) { ' ' + moment(event.time).format('MMMM Do YYYY h:mm') + '' if (event.details) { results += '
View Details
' - results += '
' - results += ' ' - results += ' ' details = JSON.parse(event.details) - $.each(Object.keys(details.payload), function(i, param) { - if (param == "rid") { - return true; - } - results += ' ' - results += ' ' - results += ' ' - results += ' ' - }) - results += '
ParameterValue(s)
' + param + '' + details.payload[param] + '
' - results += '
' + if (details.payload) { + results += '
' + results += ' ' + results += ' ' + $.each(Object.keys(details.payload), function(i, param) { + if (param == "rid") { + return true; + } + results += ' ' + results += ' ' + results += ' ' + results += ' ' + }) + results += '
ParameterValue(s)
' + param + '' + details.payload[param] + '
' + results += '
' + } + if (details.error) { + results += '
' + results += 'Error ' + details.error + results += '
' + } } results += '' } @@ -174,15 +181,15 @@ $(document).ready(function() { // Setup viewing the details of a result $("#resultsTable").on("click", ".timeline-event-details", function() { // Show the parameters - payloadTable = $(this).parent().find(".timeline-event-table") - if (payloadTable.is(":visible")) { + payloadResults = $(this).parent().find(".timeline-event-results") + if (payloadResults.is(":visible")) { $(this).find("i").removeClass("fa-caret-down") $(this).find("i").addClass("fa-caret-right") - payloadTable.hide() + payloadResults.hide() } else { $(this).find("i").removeClass("fa-caret-right") $(this).find("i").addClass("fa-caret-down") - payloadTable.show() + payloadResults.show() } }) // Setup our graphs diff --git a/static/js/app/campaigns.js b/static/js/app/campaigns.js index e6c7052b..d12d4736 100644 --- a/static/js/app/campaigns.js +++ b/static/js/app/campaigns.js @@ -35,6 +35,7 @@ function launch() { host: $("input[name=host]").val(), username: $("input[name=username]").val(), password: $("input[name=password]").val(), + ignore_cert_errors: $("#ignore_cert_errors").prop("checked") }, groups: groups } @@ -73,6 +74,7 @@ function sendTestEmail() { host: $("input[name=host]").val(), username: $("input[name=username]").val(), password: $("input[name=password]").val(), + ignore_cert_errors: $("#ignore_cert_errors").prop("checked") } } btnHtml = $("#sendTestModalSubmit").html() diff --git a/templates/campaigns.html b/templates/campaigns.html index e1c807f2..4075ed79 100644 --- a/templates/campaigns.html +++ b/templates/campaigns.html @@ -96,7 +96,10 @@
-
+
+ + +
diff --git a/util/util.go b/util/util.go index 7ab57d8e..7343246c 100644 --- a/util/util.go +++ b/util/util.go @@ -8,8 +8,8 @@ import ( "net/http" "net/mail" - "github.com/jordan-wright/email" "github.com/gophish/gophish/models" + "github.com/jordan-wright/email" ) // ParseMail takes in an HTTP Request and returns an Email object diff --git a/worker/worker.go b/worker/worker.go index 0044753b..fdbdb64f 100644 --- a/worker/worker.go +++ b/worker/worker.go @@ -2,6 +2,8 @@ package worker import ( "bytes" + "crypto/tls" + "encoding/json" "errors" "log" "net/mail" @@ -52,6 +54,10 @@ func processCampaign(c *models.Campaign) { if c.SMTP.Username != "" && c.SMTP.Password != "" { auth = smtp.PlainAuth("", c.SMTP.Username, c.SMTP.Password, strings.Split(c.SMTP.Host, ":")[0]) } + tc := &tls.Config{ + ServerName: c.SMTP.Host, + InsecureSkipVerify: c.SMTP.IgnoreCertErrors, + } f, err := mail.ParseAddress(c.SMTP.FromAddress) if err != nil { Logger.Println(err) @@ -108,14 +114,23 @@ func processCampaign(c *models.Campaign) { Logger.Println("Creating email using template") e.To = []string{t.Email} Logger.Printf("Sending Email to %s\n", t.Email) - err = e.Send(c.SMTP.Host, auth) + err = e.SendWithTLS(c.SMTP.Host, auth, tc) if err != nil { Logger.Println(err) + es := struct { + Error string `json:"error"` + }{ + Error: err.Error(), + } + ej, err := json.Marshal(es) + if err != nil { + Logger.Println(err) + } err = t.UpdateStatus(models.ERROR) if err != nil { Logger.Println(err) } - err = c.AddEvent(models.Event{Email: t.Email, Message: models.EVENT_SENDING_ERROR}) + err = c.AddEvent(models.Event{Email: t.Email, Message: models.EVENT_SENDING_ERROR, Details: string(ej)}) if err != nil { Logger.Println(err) } @@ -145,6 +160,10 @@ func SendTestEmail(s *models.SendTestEmailRequest) error { if s.SMTP.Username != "" && s.SMTP.Password != "" { auth = smtp.PlainAuth("", s.SMTP.Username, s.SMTP.Password, strings.Split(s.SMTP.Host, ":")[0]) } + t := &tls.Config{ + ServerName: s.SMTP.Host, + InsecureSkipVerify: s.SMTP.IgnoreCertErrors, + } f, err := mail.ParseAddress(s.SMTP.FromAddress) if err != nil { Logger.Println(err) @@ -188,7 +207,7 @@ func SendTestEmail(s *models.SendTestEmailRequest) error { e.Subject = string(subjBuff.Bytes()) e.To = []string{s.Email} Logger.Printf("Sending Email to %s\n", s.Email) - err = e.Send(s.SMTP.Host, auth) + err = e.SendWithTLS(s.SMTP.Host, auth, t) if err != nil { Logger.Println(err) // For now, let's split the error and return