aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/fetchsetup
blob: 0adf4751234c7d226199c3bb3ca41d6725ed43f1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/bin/sh

MSG() {
cat << EOF

# Fetchsetup is a shell script for creating a .fetchmailrc file,  
# that will be used by the program "fetchmail" to connect to your 
# mail domain and retrieve your mail. 
# This script is linux specific, so it may not work on another system.
# Kent Robotti <krobot@erols.com> (3-31-99)

EOF
}

if [ ! "$UID" = "0" ]; then
echo "[$LOGNAME] You need to be [root] to run this script."
echo "You could login: root"
echo "You could also try one of these: # sudo fetchsetup"
echo "                                 # su -c fetchsetup"
exit 1
fi

MSG
echo -n "Continue? (Y/n) : "
read ans
if [ "$ans" = "n" -o "$ans" = "N" ]; then
echo "Cancelled."
exit 0
fi

stty erase "^?" 2>/dev/null

echo
echo "Remote mail site?: pop.boo.com   <Your service providers mail domain name>"
echo -n "Remote mail site?: "
read SITE
echo
echo "Protocol?: pop3   <My service provider uses the 'pop3' mail protocol>"
echo "Protocol?: auto   <If not sure put: auto>"
echo "Choices: apop auto etrn imap imap-gss imap-k4 kpop pop2 pop3 rpop sdps" 
echo -n "Protocol?: "
read PROTO
echo
echo "Remote username?: jerry   <My username or login is jerry>"
echo -n "Remote username?: "
read USR
echo
echo "Remote password?: ?       <What's the password for?: $USR>"
echo -n "Remote password?: "
read PASS

echo
echo -n "Create $HOME/.fetchmailrc file? (Y/n) : "
read ans
if [ "$ans" = "n" -o "$ans" = "N" ]; then
echo
echo "Fetchsetup cancelled."
echo
exit 0
fi

echo 'poll "'$SITE'"' > $HOME/.fetchmailrc
echo "protocol $PROTO" >> $HOME/.fetchmailrc
echo 'username "'$USR'"' >> $HOME/.fetchmailrc
echo 'password "'$PASS'"' >> $HOME/.fetchmailrc
 
PROCMAIL=`type -all procmail | sed -n "1 p" | cut -d' ' -f3`  
SENDMAIL=`type -all sendmail | sed -n "1 p" | cut -d' ' -f3`  

if [ ! "$PROCMAIL" = "" ]; then
echo 'mda "'$PROCMAIL -d %s'"' >> $HOME/.fetchmailrc
MDA="1"
elif [ ! "$SENDMAIL" = "" ]; then
echo 'mda "'$SENDMAIL %s'"' >> $HOME/.fetchmailrc
MDA="2"
else
MDA="3"
fi 

echo >> $HOME/.fetchmailrc
echo
echo "This is your $HOME/.fetchmailrc file."

chmod 600 $HOME/.fetchmailrc

echo
cat $HOME/.fetchmailrc

if [ ! "$MAIL" = "" ]; then
echo "Fetchmail will retrieve your mail and put it in:"
echo "$MAIL"
if [ ! -f "$MAIL" ]; then
touch $MAIL 2>/dev/null
chmod 600 $MAIL 2>/dev/null
fi
fi

echo
if [ "$MDA" = "1" ]; then
echo "I put that (m)ail (d)elivery (a)gent in .fetchmailrc"
echo "because i found it on your system, this doesn't mean" 
echo "it's correct or the one you want to use."
echo
echo "The first time you run fetchmail, you should run it"
echo "this way: # fetchmail -k"
echo
elif [ "$MDA" = "2" ]; then
echo "You seem to have sendmail, sendmail will be used"
echo "as the (m)ail (d)elivery (a)gent for fetchmail."
echo
echo "WARNING! There's no way to know if sendmail is set up"
echo "properly for local mail delivery, so the first time you"
echo "run fetchmail run it this way: # fetchmail -k"
echo
echo "If the mail that fetchmail retrieves is not put in your mailbox," 
echo "you'll know that sendmail is not set up properly for the delivery" 
echo "of local mail."
echo
elif [ "$MDA" = "3" ]; then
echo "I Don't know what (m)ail (d)elivery (a)gent you're going to use."
echo "You need a <mda> to deliver the mail to you, after <fetchmail> retrieves it."
echo
echo "Put the <mda> in your .fetchmailrc file, like below."
echo "password $PASS"
echo mda '"/usr/bin/procmail -d %s"'
echo mda '"/usr/sbin/sendmail %s"'
echo
echo "The first time you run fetchmail, you should run it"
echo "this way: # fetchmail -k"
echo
fi
pan>service) + 1 + strlen(hostname) + 1; buf1 = (char *)xmalloc(buf1siz); snprintf(buf1, buf1siz, "%s@%s", service, hostname); request_buf.value = buf1; request_buf.length = strlen(buf1) + 1; maj_stat = gss_import_name(&min_stat, &request_buf, GSS_C_NT_HOSTBASED_SERVICE, target_name); if (maj_stat != GSS_S_COMPLETE) { decode_status("gss_import_name", maj_stat, min_stat, stderr); report(stderr, GT_("Couldn't get service name for [%s]\n"), buf1); return PS_AUTHFAIL; } else if (outlevel >= O_DEBUG && verbose) { (void)gss_display_name(&min_stat, *target_name, &request_buf, NULL); report(stderr, GT_("Using service name [%s]\n"), (char *)request_buf.value); } (void)gss_release_buffer(&min_stat, &request_buf); return PS_SUCCESS; } /* If we don't have suitable credentials, don't bother trying GSSAPI, but * fail right away. This is to avoid that a server - such as Microsoft * Exchange 2007 - gets wedged and refuses different authentication * mechanisms afterwards. */ int check_gss_creds(const char *service, const char *hostname) { OM_uint32 maj_stat, min_stat; gss_cred_usage_t cu; gss_name_t target_name; (void)import_name(service, hostname, &target_name, FALSE); (void)gss_release_name(&min_stat, &target_name); maj_stat = gss_inquire_cred(&min_stat, GSS_C_NO_CREDENTIAL, NULL, NULL, &cu, NULL); if (maj_stat != GSS_S_COMPLETE || (cu != GSS_C_INITIATE && cu != GSS_C_BOTH)) { if (outlevel >= O_DEBUG) { decode_status("gss_inquire_cred", maj_stat, min_stat, stdout); report(stdout, GT_("No suitable GSSAPI credentials found. Skipping GSSAPI authentication.\n")); report(stdout, GT_("If you want to use GSSAPI, you need credentials first, possibly from kinit.\n")); } return PS_AUTHFAIL; } return PS_SUCCESS; } int do_gssauth(int sock, const char *command, const char *service, const char *hostname, const char *username) { gss_buffer_desc request_buf, send_token; gss_buffer_t sec_token; gss_name_t target_name; gss_ctx_id_t context; gss_qop_t quality; int cflags; OM_uint32 maj_stat, min_stat; char buf1[8192], buf2[8192], server_conf_flags; unsigned long buf_size; int result; result = import_name(service, hostname, &target_name, TRUE); if (result) return result; gen_send(sock, "%s GSSAPI", command); /* upon receipt of the GSSAPI authentication request, server returns * a null data ready challenge to us. */ result = gen_recv(sock, buf1, sizeof buf1); if (result) return result; if (buf1[0] != '+' || strspn(buf1 + 1, " \t") < strlen(buf1 + 1)) { if (outlevel >= O_VERBOSE) { report(stdout, GT_("Received malformed challenge to \"%s GSSAPI\"!\n"), command); } goto cancelfail; } /* now start the security context initialisation loop... */ sec_token = GSS_C_NO_BUFFER; context = GSS_C_NO_CONTEXT; if (outlevel >= O_VERBOSE) report(stdout, GT_("Sending credentials\n")); do { send_token.length = 0; send_token.value = NULL; maj_stat = gss_init_sec_context(&min_stat, GSS_C_NO_CREDENTIAL, &context, target_name, GSS_C_NO_OID, GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG, 0, GSS_C_NO_CHANNEL_BINDINGS, sec_token, NULL, &send_token, NULL, NULL); if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED) { if (outlevel >= O_VERBOSE) decode_status("gss_init_sec_context", maj_stat, min_stat, stdout); (void)gss_release_name(&min_stat, &target_name); cancelfail: /* wake up server and cancel authentication */ suppress_tags = TRUE; gen_send(sock, "*"); suppress_tags = FALSE; result = gen_recv(sock, buf1, sizeof buf1); if (outlevel >= O_VERBOSE) report(stderr, GT_("Error exchanging credentials\n")); if (result) return result; return PS_AUTHFAIL; } to64frombits(buf1, send_token.value, send_token.length, sizeof buf1); gss_release_buffer(&min_stat, &send_token); suppress_tags = TRUE; gen_send(sock, "%s", buf1); suppress_tags = FALSE; if (maj_stat == GSS_S_CONTINUE_NEEDED) { result = gen_recv(sock, buf1, sizeof buf1); if (result) { gss_release_name(&min_stat, &target_name); return result; } request_buf.length = from64tobits(buf2, buf1 + 2, sizeof(buf2)); if ((int)request_buf.length == -1) /* in case of bad data */ request_buf.length = 0; request_buf.value = buf2; sec_token = &request_buf; } } while (maj_stat == GSS_S_CONTINUE_NEEDED); gss_release_name(&min_stat, &target_name); /* get security flags and buffer size */ result = gen_recv(sock, buf1, sizeof buf1); if (result) return result; request_buf.length = from64tobits(buf2, buf1 + 2, sizeof(buf2)); if ((int)request_buf.length == -1) /* in case of bad data */ request_buf.length = 0; request_buf.value = buf2; maj_stat = gss_unwrap(&min_stat, context, &request_buf, &send_token, &cflags, &quality); if (maj_stat != GSS_S_COMPLETE) { decode_status("gss_unwrap", maj_stat, min_stat, stderr); report(stderr, GT_("Couldn't unwrap security level data\n")); gss_release_buffer(&min_stat, &send_token); goto cancelfail; } if (outlevel >= O_DEBUG) report(stdout, GT_("Credential exchange complete\n")); /* first octet is security levels supported. We want none, for now */ server_conf_flags = ((char *)send_token.value)[0]; if ( !(((char *)send_token.value)[0] & GSSAUTH_P_NONE) ) { report(stderr, GT_("Server requires integrity and/or privacy\n")); gss_release_buffer(&min_stat, &send_token); goto cancelfail; } ((char *)send_token.value)[0] = 0; buf_size = ntohl(*((long *)send_token.value)); /* we don't care about buffer size if we don't wrap data */ gss_release_buffer(&min_stat, &send_token); if (outlevel >= O_DEBUG) { report(stdout, GT_("Unwrapped security level flags: %s%s%s\n"), server_conf_flags & GSSAUTH_P_NONE ? "N" : "-", server_conf_flags & GSSAUTH_P_INTEGRITY ? "I" : "-", server_conf_flags & GSSAUTH_P_PRIVACY ? "C" : "-"); report(stdout, GT_("Maximum GSS token size is %ld\n"),buf_size); } /* now respond in kind (hack!!!) */ buf_size = htonl(buf_size); /* do as they do... only matters if we do enc */ memcpy(buf1, &buf_size, 4); buf1[0] = GSSAUTH_P_NONE; if (strlcpy(buf1 + 4, username, sizeof(buf1) - 4) >= sizeof(buf1) - 4) { report(stderr, GT_("GSSAPI username too long for static buffer.\n")); goto cancelfail; } /* server decides if princ is user */ request_buf.length = 4 + strlen(username); request_buf.value = buf1; maj_stat = gss_wrap(&min_stat, context, 0, GSS_C_QOP_DEFAULT, &request_buf, &cflags, &send_token); if (maj_stat != GSS_S_COMPLETE) { report(stderr, GT_("Error creating security level request\n")); goto cancelfail; } if ((send_token.length + 3) * 4/3 >= sizeof(buf1) - 1) { report(stderr, GT_("GSSAPI send_token too large (%lu) while sending username.\n"), (unsigned long)send_token.length); goto cancelfail; } to64frombits(buf1, send_token.value, send_token.length, sizeof buf1); suppress_tags = TRUE; result = gen_transact(sock, "%s", buf1); suppress_tags = FALSE; /* flush security context */ if (outlevel >= O_DEBUG) report(stdout, GT_("Releasing GSS credentials\n")); maj_stat = gss_delete_sec_context(&min_stat, &context, &send_token); if (maj_stat != GSS_S_COMPLETE) { decode_status("gss_delete_sec_context", maj_stat, min_stat, stderr); report(stderr, GT_("Error releasing credentials\n")); return PS_AUTHFAIL; } /* send_token may contain a notification to the server to flush * credentials. RFC 1731 doesn't specify what to do, and since this * support is only for authentication, we'll assume the server * knows enough to flush its own credentials */ gss_release_buffer(&min_stat, &send_token); if (result) return(result); else return(PS_SUCCESS); } #endif /* GSSAPI */ /* gssapi.c ends here */